knitr::opts_chunk$set(echo = TRUE)
library(latex2exp)
library(IsoPriceR)
Attaching package: ‘IsoPriceR’
The following object is masked _by_ ‘.GlobalEnv’:
sample_g
library(ggplot2)
setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
getwd()
[1] "/Users/goffard/code/market_based_insurance_ratemaking/notebooks"
Let \(X\) be a random variable that
represents the total health related over a given time period, say one
year, associated to a pet. Our goal is to find the parameter \(\theta\) that best explains our market data
made of insurance quotes \[
\tilde{p}_i = f_i\left[\mathbb{E}(g_i(X))\right],\text{ }i = 1,\ldots,
n,
\] where \(g_i\) are the
coverage functions and \(f_i\) are the
loading function. The coverage functions are known and of the form \[
g(x) = \min(\max(r\cdot x - d, 0), l),
\] where \(r\) is the rate of
coverage, \(d\) is the deductible and
\(l\) is the limit.The loading
functions are unknown and will be approximated by a generic function
\(f\).
In the first section we consider the problem of finding \(\theta\) if we know access to the pure
premiums
\[
p_i = \left[\mathbb{E}(g_i(X))\right],\text{ }i = 1,\ldots, n,
\] which is not a realistic situation in practice. We then
consider an isotonic regression model to approximate \(f\) and compares it to a parametric curve,
linear withe \(f(x) = a + b\cdot x\)
for simplicity. We consider an example where
\[
X = \sum_{k=1}^NU_k,
\] where \(N\sim\text{Pois}(\lambda =
3)\) and the \(U_k\) are iid and
lognormally distributed \(U\sim\text{LogNormal}(\mu =0 , \sigma =
1)\)
set.seed(142)
# Loss model
freq_dist <- model("poisson", c("lambda"))
sev_dist <- model("lognormal", c("mu", "sigma"))
l_m <- loss_model(freq_dist, sev_dist, "Poisson-Lognormal")
# True parameter
lambda_true <- 3; mu_true <- 0; sigma_true <- 1
true_parms <- t(as.matrix(c(lambda_true, mu_true, sigma_true)))
colnames(true_parms) <- l_m$parm_names
# Data
## Sample of claim data to calculate the true pure premium via Monte Carlo
X_true <- sample_X(l_m, true_parms, R = 10000)
summary(X_true)
V1
Min. : 0.000
1st Qu.: 1.705
Median : 3.765
Mean : 4.946
3rd Qu.: 6.772
Max. :76.830
I - Generalized method of moments
If the pure premiums
\[
p_i = \mathbb{E}_(g_i(X)),\text{ }i = 1,\ldots, n,
\]
are available then our estimation problem becomes find \(\theta\) that minimizes
\[
d\left[p_{1:n},p_{1:n}^\theta\right] = \sum_i w_i^{RMSE}(p_i
-p_i^\theta)^2,
\]
where \(p_i^\theta =
\mathbb{E}_{\theta}(g_i(X))\). Identifiability holds if there
exists a unique \(\theta^*\) such
that
\[
\theta^* = \underset{\theta\in \Theta}{\text{argmin}}\,
d\left[p_{1:n},p_{1:n}^\theta\right].
\]
This condition ressembles the global identification conditions of the
Generalized Method of Moments which is typically hard to show. Existence
of minimum requires that \(\theta\mapsto
d\left[p_{1:n},p_{1:n}^\theta\right]\) is continuous and that
\(\Theta\) is compact. Uniqueness would
then hold if \(\theta\mapsto
d\left[p_{1:n},p_{1:n}^\theta\right]\) is strictly convex. This
condition is difficult to verify because an analytical expression of
\(\theta\mapsto
d\left[p_{1:n},p_{1:n}^\theta\right]\) is out of our reach and
this for almost all the compound sum \(X\). A necessary condition is that the
dimension of \(\theta\) is lower than
\(n\) which is the number of moments we
hold. Let us consider the case \(n =
3\) with
\[
g_1 = 0.85\cdot X\text{, } g_2 = \max(X - 1.8, 0) \text{, and }g_3 =
\min(X, 6)
\]
it is equivalent to the coverages \((r_1 =
0.85, d_1 = 0, l_1 = \infty)\), \((r_2
= 1, d_2 = 1.8, l_2 = \infty)\), and \((r_3 = 1, d_3 = 0, l_3 = 6)\).
## Characteristics of the pure premium which depends on the parameter of the insurance coverage
p_p <- pure_premium("xs", c("r", "d", "l"))
## Random premium parameters
n <- 3; r <- c(0.75, 1, 1); d <- c(0, 1.8, 0); l <- c(Inf, Inf, 6)
## Data frame with the insurance coverage parameters and the pure premium
th_premium <- matrix(c(r, d, l), nrow = n)
pps <- compute_pure_premia(X_true, coverage_type = "xs", th_premium)
sds <- sd_pure_premia(X_true, coverage_type = "xs", th_premium)
df_pp <- data.frame(r = r, d = d, l = l, pp=pps)
df_pp
The pure premium computed above corresponds to a well specified case
where there exists \(\theta^* =
\theta_0\) for which
\[
d\left[p_{1:n},p_{1:n}^{\theta^{\ast}}\right] = 0
\] Note that we assign the same weight to each if the pre
premium. We can check the uniqueness empirically, first in one dimension
as we plot the functions \(\sigma\mapsto
d\left[p_{1:n},p_{1:n}^{\theta^{\ast}}\right]\Big\rvert_{\mu =0, \lambda
= 3}\), \(\mu\mapsto
d\left[p_{1:n},p_{1:n}^{\theta^{\ast}}\right]\Big\rvert_{\sigma =1,
\lambda = 3}\), and \(\lambda\mapsto
d\left[p_{1:n},p_{1:n}^{\theta^{\ast}}\right]\Big\rvert_{\mu =0, \sigma
= 1}\)
data <- df_pp[,c("r", "d", "l")]
data["x"] <- df_pp$pp
ths_premium <- as.matrix(data[p_p$parm_names])
lambda_true <- 3; mu_true <- 0; sigma_true <- 1
# Sigma --------------
# Pure premium calculation for a range of risk model parameters
sigmas <- seq(0.1, 2, 0.1)
cloud <- as.matrix(expand.grid(c(3), c(0),sigmas))
colnames(cloud) <- l_m$parm_names
X <- sample_X(l_m , cloud, R = 10000)
pp_fake <- compute_pure_premia(X, coverage_type = "xs", ths_premium)
# Calculation of the RMSE between true and wrong pure premium
ds <- sapply(1:nrow(cloud), function(k) mean((pp_fake[, k] - data$x)^2)^(1/2))
df_ds <- data.frame(cloud)
df_ds <- cbind(df_ds, ds)
(sig_pure_RMSE <- ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds)) + ggplot2::theme_classic(base_size = 14) + labs(x = expression(sigma), title = "RMSE", y = "") )
ggsave("../figures/sig_pure_RMSE.pdf", sig_pure_RMSE)
Saving 7.29 x 4.51 in image

# Lambda --------------
lambdas <- seq(0.1, 5, 0.1)
cloud <- as.matrix(expand.grid(lambdas, c(0),c(1)))
colnames(cloud) <- l_m$parm_names
X <- sample_X(l_m , cloud, R = 10000)
pp_fake <- compute_pure_premia(X, coverage_type = "xs", ths_premium)
# Calculation of the RMSE between true and wrong pure premium
ds <- sapply(1:nrow(cloud), function(k) mean((pp_fake[, k] - data$x)^2)^(1/2))
df_ds <- data.frame(cloud)
df_ds <- cbind(df_ds, ds)
(lambda_pure_RMSE <- ggplot(data = df_ds) + geom_line(mapping = aes(x = lambda, y = ds)) + ggplot2::theme_classic(base_size = 14) + labs(x = expression(lambda), title = "RMSE", y = "") )
ggsave("../figures/lambda_pure_RMSE.pdf", lambda_pure_RMSE)
Saving 7.29 x 4.51 in image

# mu --------------
mus <- seq(-3, 3, 0.1)
cloud <- as.matrix(expand.grid(c(3), mus,c(1)))
colnames(cloud) <- l_m$parm_names
X <- sample_X(l_m , cloud, R = 10000)
pp_fake <- compute_pure_premia(X, coverage_type = "xs", ths_premium)
# Calculation of the RMSE between true and wrong pure premium
ds <- sapply(1:nrow(cloud), function(k) mean((pp_fake[, k] - data$x)^2)^(1/2))
df_ds <- data.frame(cloud)
df_ds <- cbind(df_ds, ds)
(mu_pure_RMSE <- ggplot(data = df_ds) + geom_line(mapping = aes(x = mu, y = ds)) + ggplot2::theme_classic(base_size = 14) + labs(x = expression(mu), title = "RMSE", y = "") )
ggsave("../figures/mu_pure_RMSE.pdf", mu_pure_RMSE)
Saving 7.29 x 4.51 in image

Each parameters can be identified separately, now of course
identifying them jointly is another matter, there might exists several
combinations of parameters that yield the same pure premium. Our
optimization allows us to investigate by searching efficiently the
parameter space.
We use the follwing prior assumptions: \[
\lambda\sim\text{Unif}(0, 10)\text{, }\mu\sim\text{Unif}(-3, 3)\text{,
and }\sigma\sim\text{Unif}(0, 5)
\] and the following settings for the algorithm
\[
J = 500\text{ and }R = 500
\] Recall that \(J\) is the
population size of the clouds of particles and \(R\) is the number of Monte Carlo
replications.
# Prior settings for the parameters
prior_lambda <- prior_dist("uniform", "lambda",c(0, 10))
prior_mu <- prior_dist("uniform", "mu",c(-3,3))
prior_sigma <- prior_dist("uniform", "sigma", c(0, 5))
prior_distributions <- list(prior_lambda, prior_mu, prior_sigma)
model_prior <- independent_priors(prior_distributions)
# Settings for the abc algorithm
popSize <- 500; MC_R<- 500; acc <- 10; sp_bounds <- c(1, 1); eps_min <- 0.02
sum(sds/sqrt(MC_R)^2)
data <- df_pp[,c("r", "d", "l")]
data["x"] <- df_pp$pp
# res_abc <- abc(data, model_prior, l_m, p_p, popSize, MC_R, acc, sp_bounds, eps_min)
# save(res_abc, file = "../data/res_abc_supp_material_Section1.RData")
load("../data/res_abc_supp_material_Section1.RData")
# We retrieve the cloud of particles associated to each generation
cloud_dfs <- lapply(res_abc$Clouds, as.data.frame)
cloud_df <- do.call(rbind, cloud_dfs)
cloud_df$generation <- sort(rep(1:length(res_abc$Clouds), popSize))
cloud_df_plot <- rbind(
data.frame(parm = cloud_df$lambda, parm_name = "lambda", generation = cloud_df$generation),
data.frame(parm = cloud_df$sigma, parm_name = "sigma", generation = cloud_df$generation)
)
cloud_df_plot$parm_name <-as.factor(cloud_df_plot$parm_name)
levels(cloud_df_plot$parm_name) <- c(lambda = TeX("$\\lambda$"), sigma = TeX("$\\sigma$"))
(posterior_lambda <- ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=lambda, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\lambda$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,1]), color="black",
linetype="dashed"))
ggsave("../figures/posterior_lambda_supp_mat.pdf", posterior_lambda)
(posterior_mu <- ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=mu, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\mu$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,2]), color="black",
linetype="dashed"))
ggsave("../figures/posterior_mu_supp_mat.pdf", posterior_mu)
(posterior_sig <- ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=sigma, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\sigma$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,3]), color="black",
linetype="dashed"))
ggsave("../figures/posterior_sig_supp_mat.pdf", posterior_sig)
II - Optimization based on the commercial premiums without
regularization
We do not have access to the pure premium, instead we have the
commercial premiums
\[
\tilde{p}_i = f_i\left[\mathbb{E}(g_i(X))\right],\text{ }i = 1,\ldots,
n,
\]
where the loading functions must be approximated. We therefore have
to choose a model \(f\) such that
\[
\tilde{p}_i = f(p_{i}^\theta),\text{ }i = 1,\ldots, n
\] and hope that there exists a unique \(\theta^*\) such that
\[
\theta^* = \underset{\theta\in \Theta}{\text{argmin}}\,
d\left[\tilde{p}_{1:n},f(p_{1:n}^\theta)\right].
\] This typically depends on the choice for \(f\) we consider isotonic and linear.
Isotonic regression impose monotonicity which is desirable since we
believe it would make sense if
\[
p_i > p_j\Rightarrow \tilde{p}_i > \tilde{p}_j.
\]
Furthermore isotonic regression is non parametric which mitigate the
risk of misspecification. The drawback is overfitting as perfect
interpolation of may occur in a small sample size setting.
Well-specified case
In our example we take the following loading fuunctions
\[
f_1(x) = 1.1\cdot x\text{, }f_2(x) = 1.2\cdot x \text{, and } f_3(x) =
1.3\cdot x
\]
data <- df_pp[,c("r", "d", "l")]
data["x"] <- c(df_pp$pp[1]*1.38 , df_pp$pp[2]*1.1 , df_pp$pp[3] * 1.4 )
# data["x"] <- df_pp$pp
ths_premium <- as.matrix(data[p_p$parm_names])
lambda_true <- 3; mu_true <- 0; sigma_true <- 1
(pp_cp_well_specified <- ggplot() + geom_point(mapping = aes(x = df_pp$pp, y = data$x)) + ggplot2::theme_classic(base_size = 14) + labs(x = "Pure Premium", title = "Commercial premium", y = "") )
ggsave("../figures/pp_cp_well_specified.pdf", pp_cp_well_specified)
Saving 7.29 x 4.51 in image

# Sigma --------------
# Pure premium calculation for a range of risk model parameters
sigmas <- seq(0.1, 2, 0.02)
cloud <- as.matrix(expand.grid(c(3), c(0),sigmas))
colnames(cloud) <- l_m$parm_names
X <- sample_X(l_m , cloud, R = 10000)
pp_fake <- compute_pure_premia(X, coverage_type = "xs", ths_premium)
# Calculation of the RMSE between true and wrong commercial premium
ress_iso <- lapply(1:ncol(pp_fake), function(k) isoreg(pp_fake[, k], data$x))
ress_lm <- sapply(1:ncol(pp_fake), function(k) as.numeric(lm(data$x~pp_fake[, k] - 1)$coefficients))
ress_lm[sigmas == 1]
[1] 1.297967
as.numeric(lm(data$x ~ pp_fake[, sigmas == 1] - 1)$coefficients)
[1] 1.297967
mean((mean((pp_fake[, sigmas == 1] * ress_lm[sigmas == 1] - data$x)^2)^(1/2) - data$x)^2)^(1/2)
[1] 4.20526
fs_iso <- lapply(ress_iso, function(res_iso) stepfun(sort(res_iso$x), c(min(res_iso$yf) /2 ,
res_iso$yf), f = 1))
ds_iso <- sapply(1:nrow(cloud), function(k) mean((fs_iso[[k]](pp_fake[, k]) - data$x)^2)^(1/2))
ds_lm <- sapply(1:nrow(cloud), function(k) mean((pp_fake[, k] / ress_lm[k] - data$x)^2)^(1/2))
df_ds <- data.frame(cloud)
df_ds <- cbind(df_ds, ds_iso)
df_ds <- cbind(df_ds, ds_lm)
ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds_iso))

ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds_lm))

sigmas[ds_lm == min(ds_lm)]
[1] 1.22
# Prior settings for the parameters
prior_lambda <- prior_dist("uniform", "lambda",c(0, 5))
prior_mu <- prior_dist("uniform", "mu",c(-3,3))
prior_sigma <- prior_dist("uniform", "sigma", c(0, 2))
prior_distributions <- list(prior_lambda, prior_mu, prior_sigma)
model_prior <- independent_priors(prior_distributions)
# Settings for the abc algorithm
popSize <- 500; MC_R<- 500; acc <- 0.01; sp_bounds <- c(10^(-16), Inf); eps_min <- 0.01
res_abc <- abc(data, model_prior, l_m, p_p, popSize, MC_R, acc, sp_bounds, eps_min)
[1] "Sampling generation of particles 1 ; eps = Inf ; ESS = 500"
[1] "Sampling generation of particles 2 ; eps = 0.638654634426981 ; ESS = 250"
===============================================================================================================================================================================================
[1] 23
[1] "Sampling generation of particles 3 ; eps = 0.0179453779610254 ; ESS = 250.653519160833"
===============================================================================================================================================================================================
[1] 500
[1] "Sampling generation of particles 4 ; eps = 0.01 ; ESS = 250.706714954091"
===============================================================================================================================================================================================
[1] 500
# We retrieve the cloud of particles associated to each generation
cloud_dfs <- lapply(res_abc$Clouds, as.data.frame)
cloud_df <- do.call(rbind, cloud_dfs)
cloud_df$generation <- sort(rep(1:length(res_abc$Clouds), popSize))
cloud_df_plot <- rbind(
data.frame(parm = cloud_df$lambda, parm_name = "lambda", generation = cloud_df$generation),
data.frame(parm = cloud_df$sigma, parm_name = "sigma", generation = cloud_df$generation)
)
cloud_df_plot$parm_name <-as.factor(cloud_df_plot$parm_name)
levels(cloud_df_plot$parm_name) <- c(lambda = TeX("$\\lambda$"), sigma = TeX("$\\sigma$"))
ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=lambda, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\lambda$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,1]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=mu, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\mu$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,2]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=sigma, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\sigma$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,3]), color="black",
linetype="dashed")

III - Optimization based on the commercial premiums with
regularization
# Adding the regularization terms
sp_bounds <- c(min(df_pp$pp / data$x), max(df_pp$pp / data$x))
# sp_bounds <- c(0.6, 0.95)
ds1 <- sapply(1:ncol(pp_fake), function(k) sqrt(mean((pmax(data$x - pp_fake[,k] /sp_bounds[1], 0) )^2)))
ds2 <- sapply(1:ncol(pp_fake), function(k) sqrt(mean((pmax( pp_fake[,k] / sp_bounds[2] - data$x , 0) )^2)))
ds_iso_reg <- ds_iso + ds1 + ds2
ds_lm_reg <- ds_lm + ds1 + ds2
df_ds <- data.frame(cloud)
df_ds <- cbind(df_ds, ds_iso_reg, ds_lm_reg)
ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds_iso_reg))

ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds_lm_reg))

print(sigmas[ds_lm_reg==min(ds_lm_reg)])
[1] 1.16
print(sigmas[ds_iso_reg==min(ds_iso_reg)])
[1] 1
# Prior settings for the parameters
prior_lambda <- prior_dist("uniform", "lambda",c(0, 5))
prior_mu <- prior_dist("uniform", "mu",c(-3,3))
prior_sigma <- prior_dist("uniform", "sigma", c(0, 2))
prior_distributions <- list(prior_lambda, prior_mu, prior_sigma)
model_prior <- independent_priors(prior_distributions)
# Settings for the abc algorithm
popSize <- 500; MC_R<- 500; acc <- 0.001; sp_bounds <- c(min(df_pp$pp / data$x), max(df_pp$pp / data$x))
eps_min <- 0.0001
res_abc <- abc(data, model_prior, l_m, p_p, popSize, MC_R, acc, sp_bounds, eps_min)
[1] "Sampling generation of particles 1 ; eps = Inf ; ESS = 500"
[1] "Sampling generation of particles 2 ; eps = 4.43689039270973 ; ESS = 250"
===============================================================================================================================================================================================
[1] 260
[1] "Sampling generation of particles 3 ; eps = 3.35330585831361 ; ESS = 250.772464133936"
===============================================================================================================================================================================================
[1] 263
[1] "Sampling generation of particles 4 ; eps = 2.23229920434542 ; ESS = 250.886475662332"
===============================================================================================================================================================================================
[1] 257
[1] "Sampling generation of particles 5 ; eps = 1.34653967981587 ; ESS = 250.030381611654"
===============================================================================================================================================================================================
[1] 259
[1] "Sampling generation of particles 6 ; eps = 0.731400077523843 ; ESS = 250.89930191337"
===============================================================================================================================================================================================
[1] 258
[1] "Sampling generation of particles 7 ; eps = 0.319613497124356 ; ESS = 250.2391400301"
===============================================================================================================================================================================================
[1] 260
[1] "Sampling generation of particles 8 ; eps = 0.148285269745679 ; ESS = 250.259059634864"
===============================================================================================================================================================================================
[1] 268
[1] "Sampling generation of particles 9 ; eps = 0.0739579668388663 ; ESS = 250.0545936104"
===============================================================================================================================================================================================
[1] 268
[1] "Sampling generation of particles 10 ; eps = 0.021013252054564 ; ESS = 250.599302376695"
===============================================================================================================================================================================================
[1] 15
[1] "Sampling generation of particles 11 ; eps = 0.0179453779610254 ; ESS = 250.574578198601"
===============================================================================================================================================================================================
[1] 290
[1] "Sampling generation of particles 12 ; eps = 0.00378496163232778 ; ESS = 250.632080483012"
===============================================================================================================================================================================================
[1] 427
[1] "Sampling generation of particles 13 ; eps = 1e-04 ; ESS = 250.70095264432"
===============================================================================================================================================================================================
[1] 500
[1] "Sampling generation of particles 14 ; eps = 1e-04 ; ESS = 250.701552548448"
===============================================================================================================================================================================================
[1] 500
# We retrieve the cloud of particles associated to each generation
cloud_dfs <- lapply(res_abc$Clouds, as.data.frame)
cloud_df <- do.call(rbind, cloud_dfs)
cloud_df$generation <- sort(rep(1:length(res_abc$Clouds), popSize))
cloud_df_plot <- rbind(
data.frame(parm = cloud_df$lambda, parm_name = "lambda", generation = cloud_df$generation),
data.frame(parm = cloud_df$sigma, parm_name = "sigma", generation = cloud_df$generation)
)
cloud_df_plot$parm_name <-as.factor(cloud_df_plot$parm_name)
levels(cloud_df_plot$parm_name) <- c(lambda = TeX("$\\lambda$"), sigma = TeX("$\\sigma$"))
ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=lambda, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\lambda$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,1]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=mu, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\mu$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,2]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=sigma, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\sigma$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,3]), color="black",
linetype="dashed")

res_abc$ds[[13]]
[1] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[15] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[29] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 8.540344e-05 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[43] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[57] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[71] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[85] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[99] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[113] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[127] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[141] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[155] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[169] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[183] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[197] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[211] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[225] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[239] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[253] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[267] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[281] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[295] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[309] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[323] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[337] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[351] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[365] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[379] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[393] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[407] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[421] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[435] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[449] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[463] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[477] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
[491] 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16 7.251946e-16
Well-specified case
In our example we take the following loading fuunctions
\[
f_1(x) = 1.1\cdot x\text{, }f_2(x) = 1.2\cdot x \text{, and } f_3(x) =
1.3\cdot x
\]
data <- df_pp[,c("r", "d", "l")]
data["x"] <- c(df_pp$pp[1]*1.1 , df_pp$pp[2]*1.2 , df_pp$pp[3] * 1.3 )
# data["x"] <- df_pp$pp
ths_premium <- as.matrix(data[p_p$parm_names])
lambda_true <- 3; mu_true <- 0; sigma_true <- 1
(pp_cp_well_specified <- ggplot() + geom_point(mapping = aes(x = df_pp$pp, y = data$x)) + ggplot2::theme_classic(base_size = 14) + labs(x = "Pure Premium", title = "Commercial premium", y = "") )
ggsave("../figures/pp_cp_well_specified.pdf", pp_cp_well_specified)
Saving 7.29 x 4.51 in image

# Sigma --------------
# Pure premium calculation for a range of risk model parameters
sigmas <- seq(0.1, 2, 0.02)
cloud <- as.matrix(expand.grid(c(3), c(0),sigmas))
colnames(cloud) <- l_m$parm_names
X <- sample_X(l_m , cloud, R = 10000)
pp_fake <- compute_pure_premia(X, coverage_type = "xs", ths_premium)
# Calculation of the RMSE between true and wrong commercial premium
ress_iso <- lapply(1:ncol(pp_fake), function(k) isoreg(pp_fake[, k], data$x))
ress_lm <- sapply(1:ncol(pp_fake), function(k) as.numeric(lm(data$x~pp_fake[, k] - 1)$coefficients))
ress_lm[sigmas == 1]
[1] 1.19087
as.numeric(lm(data$x ~ pp_fake[, sigmas == 1] - 1)$coefficients)
[1] 1.19087
mean((mean((pp_fake[, sigmas == 1] * ress_lm[sigmas == 1] - data$x)^2)^(1/2) - data$x)^2)^(1/2)
[1] 3.984624
fs_iso <- lapply(ress_iso, function(res_iso) stepfun(sort(res_iso$x), c(min(res_iso$yf) /2 ,
res_iso$yf), f = 1))
ds_iso <- sapply(1:nrow(cloud), function(k) mean((fs_iso[[k]](pp_fake[, k]) - data$x)^2)^(1/2))
ds_lm <- sapply(1:nrow(cloud), function(k) mean((pp_fake[, k] / ress_lm[k] - data$x)^2)^(1/2))
df_ds <- data.frame(cloud)
df_ds <- cbind(df_ds, ds_iso)
df_ds <- cbind(df_ds, ds_lm)
ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds_iso))

ggplot(data = df_ds) + geom_line(mapping = aes(x = sigma, y = ds_lm))

sigmas[ds_lm == min(ds_lm)]
[1] 1.16
# Prior settings for the parameters
prior_lambda <- prior_dist("uniform", "lambda",c(0, 5))
prior_mu <- prior_dist("uniform", "mu",c(-3,3))
prior_sigma <- prior_dist("uniform", "sigma", c(0, 2))
prior_distributions <- list(prior_lambda, prior_mu, prior_sigma)
model_prior <- independent_priors(prior_distributions)
# Settings for the abc algorithm
popSize <- 500; MC_R<- 500; acc <- 0.01; sp_bounds <- c(10^(-16), Inf); eps_min <- 0.01
res_abc <- abc(data, model_prior, l_m, p_p, popSize, MC_R, acc, sp_bounds, eps_min)
[1] "Sampling generation of particles 1 ; eps = Inf ; ESS = 500"
[1] "Sampling generation of particles 2 ; eps = 0.297386732987592 ; ESS = 250"
===============================================================================================================================================================================================
[1] 242
[1] "Sampling generation of particles 3 ; eps = 0.258092879599686 ; ESS = 250.503338748765"
===============================================================================================================================================================================================
[1] 500
[1] "Sampling generation of particles 4 ; eps = 0.01 ; ESS = 250.445785786703"
===============================================================================================================================================================================================
[1] 500
[1] "Sampling generation of particles 5 ; eps = 0.01 ; ESS = 250.653120238212"
===============================================================================================================================================================================================
[1] 500
# We retrieve the cloud of particles associated to each generation
cloud_dfs <- lapply(res_abc$Clouds, as.data.frame)
cloud_df <- do.call(rbind, cloud_dfs)
cloud_df$generation <- sort(rep(1:length(res_abc$Clouds), popSize))
cloud_df_plot <- rbind(
data.frame(parm = cloud_df$lambda, parm_name = "lambda", generation = cloud_df$generation),
data.frame(parm = cloud_df$sigma, parm_name = "sigma", generation = cloud_df$generation)
)
cloud_df_plot$parm_name <-as.factor(cloud_df_plot$parm_name)
levels(cloud_df_plot$parm_name) <- c(lambda = TeX("$\\lambda$"), sigma = TeX("$\\sigma$"))
ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=lambda, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\lambda$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,1]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=mu, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\mu$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,2]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=sigma, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\sigma$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,3]), color="black",
linetype="dashed")

III - Optimization based on the commercial premiums with
regularization
print(sigmas[ds_iso_reg==min(ds_iso_reg)]); print(min(ds_iso_reg))
[1] 0.96
[1] 0.001560745
# Prior settings for the parameters
prior_lambda <- prior_dist("uniform", "lambda",c(0, 5))
prior_mu <- prior_dist("uniform", "mu",c(-3,3))
prior_sigma <- prior_dist("uniform", "sigma", c(0, 2))
prior_distributions <- list(prior_lambda, prior_mu, prior_sigma)
model_prior <- independent_priors(prior_distributions)
# Settings for the abc algorithm
popSize <- 500; MC_R<- 500; acc <- 0.002; sp_bounds <- c(min(df_pp$pp / data$x), max(df_pp$pp / data$x))
eps_min <- 0.002
res_abc <- abc(data, model_prior, l_m, p_p, popSize, MC_R, acc, sp_bounds, eps_min)
[1] "Sampling generation of particles 1 ; eps = Inf ; ESS = 500"
[1] "Sampling generation of particles 2 ; eps = 3.94292337790187 ; ESS = 250"
===============================================================================================================================================================================================
[1] 264
[1] "Sampling generation of particles 3 ; eps = 2.88561559648946 ; ESS = 250.910601767801"
===============================================================================================================================================================================================
[1] 261
[1] "Sampling generation of particles 4 ; eps = 1.82835959111493 ; ESS = 250.88826264432"
===============================================================================================================================================================================================
[1] 257
[1] "Sampling generation of particles 5 ; eps = 1.12298655265911 ; ESS = 250.516480072063"
===============================================================================================================================================================================================
[1] 260
[1] "Sampling generation of particles 6 ; eps = 0.674098340085706 ; ESS = 250.233588685872"
===============================================================================================================================================================================================
[1] 256
[1] "Sampling generation of particles 7 ; eps = 0.350334206408645 ; ESS = 250.129029112909"
===============================================================================================================================================================================================
[1] 259
[1] "Sampling generation of particles 8 ; eps = 0.134850428265648 ; ESS = 250.06467485184"
===============================================================================================================================================================================================
[1] 267
[1] "Sampling generation of particles 9 ; eps = 0.0537250475762552 ; ESS = 250.750732391304"
===============================================================================================================================================================================================
[1] 270
[1] "Sampling generation of particles 10 ; eps = 0.00907367331436939 ; ESS = 250.332252647683"
===============================================================================================================================================================================================
[1] 438
[1] "Sampling generation of particles 11 ; eps = 0.002 ; ESS = 250.655511831248"
===============================================================================================================================================================================================
[1] 500
[1] "Sampling generation of particles 12 ; eps = 0.002 ; ESS = 250.455240112145"
===============================================================================================================================================================================================
[1] 500
# We retrieve the cloud of particles associated to each generation
cloud_dfs <- lapply(res_abc$Clouds, as.data.frame)
cloud_df <- do.call(rbind, cloud_dfs)
cloud_df$generation <- sort(rep(1:length(res_abc$Clouds), popSize))
cloud_df_plot <- rbind(
data.frame(parm = cloud_df$lambda, parm_name = "lambda", generation = cloud_df$generation),
data.frame(parm = cloud_df$sigma, parm_name = "sigma", generation = cloud_df$generation)
)
cloud_df_plot$parm_name <-as.factor(cloud_df_plot$parm_name)
levels(cloud_df_plot$parm_name) <- c(lambda = TeX("$\\lambda$"), sigma = TeX("$\\sigma$"))
ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=lambda, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\lambda$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,1]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=mu, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\mu$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,2]), color="black",
linetype="dashed")

ggplot2::ggplot(data = cloud_df ) + ggplot2::geom_density(data = cloud_df, mapping = aes(x=sigma, color = as.factor(generation))) + ggplot2::labs(x=TeX("$\\sigma$"), y = "Density", color = "Generation") + ggplot2::theme_classic(base_size = 20) + ggplot2::theme(legend.position="right") + ggplot2::geom_vline(ggplot2::aes(xintercept=true_parms[,3]), color="black",
linetype="dashed")

res_abc$ds[[12]]
[1] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[16] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[31] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[46] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[61] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[76] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[91] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[106] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[121] 0.001100374 0.001100374 0.001100374 0.001102460 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[136] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[151] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[166] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001842784 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[181] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[196] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[211] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[226] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[241] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001900111
[256] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001192304 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[271] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[286] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[301] 0.001100374 0.001100374 0.001108272 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[316] 0.001100374 0.001155256 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[331] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[346] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[361] 0.001100374 0.001100374 0.001100374 0.001422143 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[376] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001255541 0.001100374
[391] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001338872 0.001100374 0.001100374 0.001100374 0.001100374
[406] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[421] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[436] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[451] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[466] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[481] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
[496] 0.001100374 0.001100374 0.001100374 0.001100374 0.001100374
LS0tCnRpdGxlOiAiU3VwbGVtZW50YXJ5IG1hdGVyaWFsOiBHZW5lcmFsaXplZCBtZXRob2Qgb2YgbW9tZW50cyBhbmQgaWRlbnRpZmlhYmlsaXR5IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKbGlicmFyeShsYXRleDJleHApCmxpYnJhcnkoSXNvUHJpY2VSKQpsaWJyYXJ5KGdncGxvdDIpCnNldHdkKGRpcm5hbWUocnN0dWRpb2FwaTo6Z2V0QWN0aXZlRG9jdW1lbnRDb250ZXh0KCkkcGF0aCkpCmdldHdkKCkKYGBgCkxldCAkWCQgYmUgYSByYW5kb20gdmFyaWFibGUgdGhhdCByZXByZXNlbnRzIHRoZSB0b3RhbCBoZWFsdGggcmVsYXRlZCBvdmVyIGEgZ2l2ZW4gdGltZSBwZXJpb2QsIHNheSBvbmUgeWVhciwgYXNzb2NpYXRlZCB0byBhIHBldC4gT3VyIGdvYWwgaXMgdG8gZmluZCB0aGUgcGFyYW1ldGVyICRcdGhldGEkIHRoYXQgYmVzdCBleHBsYWlucyBvdXIgbWFya2V0IGRhdGEgbWFkZSBvZiBpbnN1cmFuY2UgcXVvdGVzCiQkClx0aWxkZXtwfV9pID0gZl9pXGxlZnRbXG1hdGhiYntFfShnX2koWCkpXHJpZ2h0XSxcdGV4dHsgfWkgPSAxLFxsZG90cywgbiwKJCQKd2hlcmUgJGdfaSQgYXJlIHRoZSBjb3ZlcmFnZSBmdW5jdGlvbnMgYW5kICRmX2kkIGFyZSB0aGUgbG9hZGluZyBmdW5jdGlvbi4gVGhlIGNvdmVyYWdlIGZ1bmN0aW9ucyBhcmUga25vd24gYW5kIG9mIHRoZSBmb3JtCiQkCmcoeCkgPSBcbWluKFxtYXgoclxjZG90IHggLSBkLCAwKSwgbCksCiQkCndoZXJlICRyJCBpcyB0aGUgcmF0ZSBvZiBjb3ZlcmFnZSwgJGQkIGlzIHRoZSBkZWR1Y3RpYmxlIGFuZCAkbCQgaXMgdGhlIGxpbWl0LlRoZSBsb2FkaW5nIGZ1bmN0aW9ucyBhcmUgdW5rbm93biBhbmQgd2lsbCBiZSBhcHByb3hpbWF0ZWQgYnkgYSBnZW5lcmljIGZ1bmN0aW9uICRmJC4gCgpJbiB0aGUgZmlyc3Qgc2VjdGlvbiB3ZSBjb25zaWRlciB0aGUgcHJvYmxlbSBvZiBmaW5kaW5nICRcdGhldGEkIGlmIHdlIGtub3cgYWNjZXNzIHRvIHRoZSBwdXJlIHByZW1pdW1zIAoKJCQKcF9pID0gXGxlZnRbXG1hdGhiYntFfShnX2koWCkpXHJpZ2h0XSxcdGV4dHsgfWkgPSAxLFxsZG90cywgbiwKJCQKd2hpY2ggaXMgbm90IGEgcmVhbGlzdGljIHNpdHVhdGlvbiBpbiBwcmFjdGljZS4gV2UgdGhlbiBjb25zaWRlciBhbiBpc290b25pYyByZWdyZXNzaW9uIG1vZGVsIHRvIGFwcHJveGltYXRlICRmJCBhbmQgY29tcGFyZXMgaXQgdG8gYSBwYXJhbWV0cmljIGN1cnZlLCBsaW5lYXIgd2l0aGUgJGYoeCkgPSBhICsgYlxjZG90IHgkIGZvciBzaW1wbGljaXR5LiBXZSBjb25zaWRlciBhbiBleGFtcGxlIHdoZXJlCgokJApYID0gXHN1bV97az0xfV5OVV9rLAokJAp3aGVyZSAkTlxzaW1cdGV4dHtQb2lzfShcbGFtYmRhID0gMykkIGFuZCB0aGUgJFVfayQgYXJlIGlpZCBhbmQgbG9nbm9ybWFsbHkgZGlzdHJpYnV0ZWQgJFVcc2ltXHRleHR7TG9nTm9ybWFsfShcbXUgPTAgLCBcc2lnbWEgPSAxKSQKCmBgYHtyfQpzZXQuc2VlZCgxNDIpCgojIExvc3MgbW9kZWwKZnJlcV9kaXN0IDwtIG1vZGVsKCJwb2lzc29uIiwgYygibGFtYmRhIikpCnNldl9kaXN0IDwtIG1vZGVsKCJsb2dub3JtYWwiLCBjKCJtdSIsICJzaWdtYSIpKQpsX20gPC0gbG9zc19tb2RlbChmcmVxX2Rpc3QsIHNldl9kaXN0LCAiUG9pc3Nvbi1Mb2dub3JtYWwiKQoKIyBUcnVlIHBhcmFtZXRlcgpsYW1iZGFfdHJ1ZSA8LSAzOyBtdV90cnVlIDwtIDA7IHNpZ21hX3RydWUgPC0gMQp0cnVlX3Bhcm1zIDwtIHQoYXMubWF0cml4KGMobGFtYmRhX3RydWUsIG11X3RydWUsIHNpZ21hX3RydWUpKSkKY29sbmFtZXModHJ1ZV9wYXJtcykgPC0gbF9tJHBhcm1fbmFtZXMKCiMgRGF0YQojIyBTYW1wbGUgb2YgY2xhaW0gZGF0YSB0byBjYWxjdWxhdGUgdGhlIHRydWUgcHVyZSBwcmVtaXVtIHZpYSBNb250ZSBDYXJsbwpYX3RydWUgPC0gc2FtcGxlX1gobF9tLCB0cnVlX3Bhcm1zLCBSID0gMTAwMDApCnN1bW1hcnkoWF90cnVlKQpgYGAKCgojIEkgLSBHZW5lcmFsaXplZCBtZXRob2Qgb2YgbW9tZW50cwoKSWYgdGhlIHB1cmUgcHJlbWl1bXMgCgokJApwX2kgPSBcbWF0aGJie0V9XyhnX2koWCkpLFx0ZXh0eyB9aSA9IDEsXGxkb3RzLCBuLAokJAoKYXJlIGF2YWlsYWJsZSB0aGVuIG91ciBlc3RpbWF0aW9uIHByb2JsZW0gYmVjb21lcyBmaW5kICRcdGhldGEkIHRoYXQgbWluaW1pemVzIAoKJCQKZFxsZWZ0W3BfezE6bn0scF97MTpufV5cdGhldGFccmlnaHRdID0gXHN1bV9pIHdfaV57Uk1TRX0ocF9pIC1wX2leXHRoZXRhKV4yLAokJAoKd2hlcmUgJHBfaV5cdGhldGEgPSBcbWF0aGJie0V9X3tcdGhldGF9KGdfaShYKSkkLiBJZGVudGlmaWFiaWxpdHkgaG9sZHMgaWYgdGhlcmUgZXhpc3RzIGEgdW5pcXVlICRcdGhldGFeKiQgc3VjaCB0aGF0IAoKJCQKXHRoZXRhXiogPSBcdW5kZXJzZXR7XHRoZXRhXGluIFxUaGV0YX17XHRleHR7YXJnbWlufX1cLCBkXGxlZnRbcF97MTpufSxwX3sxOm59Xlx0aGV0YVxyaWdodF0uCiQkCgpUaGlzIGNvbmRpdGlvbiByZXNzZW1ibGVzIHRoZSBnbG9iYWwgaWRlbnRpZmljYXRpb24gY29uZGl0aW9ucyBvZiB0aGUgR2VuZXJhbGl6ZWQgTWV0aG9kIG9mIE1vbWVudHMgd2hpY2ggaXMgdHlwaWNhbGx5IGhhcmQgdG8gc2hvdy4gRXhpc3RlbmNlIG9mIG1pbmltdW0gcmVxdWlyZXMgdGhhdCAkXHRoZXRhXG1hcHN0byBkXGxlZnRbcF97MTpufSxwX3sxOm59Xlx0aGV0YVxyaWdodF0kIGlzIGNvbnRpbnVvdXMgYW5kIHRoYXQgJFxUaGV0YSQgaXMgY29tcGFjdC4gVW5pcXVlbmVzcyB3b3VsZCB0aGVuIGhvbGQgaWYgJFx0aGV0YVxtYXBzdG8gZFxsZWZ0W3BfezE6bn0scF97MTpufV5cdGhldGFccmlnaHRdJCBpcyBzdHJpY3RseSBjb252ZXguIFRoaXMgY29uZGl0aW9uIGlzIGRpZmZpY3VsdCB0byB2ZXJpZnkgYmVjYXVzZSBhbiBhbmFseXRpY2FsIGV4cHJlc3Npb24gb2YgJFx0aGV0YVxtYXBzdG8gZFxsZWZ0W3BfezE6bn0scF97MTpufV5cdGhldGFccmlnaHRdJCBpcyBvdXQgb2Ygb3VyIHJlYWNoIGFuZCB0aGlzIGZvciBhbG1vc3QgYWxsIHRoZSBjb21wb3VuZCBzdW0gJFgkLiBBIG5lY2Vzc2FyeSBjb25kaXRpb24gaXMgdGhhdCB0aGUgZGltZW5zaW9uIG9mICRcdGhldGEkIGlzIGxvd2VyIHRoYW4gJG4kIHdoaWNoIGlzIHRoZSBudW1iZXIgb2YgbW9tZW50cyB3ZSBob2xkLiBMZXQgdXMgY29uc2lkZXIgdGhlIGNhc2UgJG4gPSAzJCB3aXRoCgokJApnXzEgPSAwLjg1XGNkb3QgWFx0ZXh0eywgfSBnXzIgPSBcbWF4KFggLSAxLjgsIDApIFx0ZXh0eywgYW5kIH1nXzMgPSBcbWluKFgsIDYpCiQkCgppdCBpcyBlcXVpdmFsZW50IHRvIHRoZSBjb3ZlcmFnZXMgJChyXzEgPSAwLjg1LCBkXzEgPSAwLCBsXzEgPSBcaW5mdHkpJCwgJChyXzIgPSAxLCBkXzIgPSAxLjgsIGxfMiA9IFxpbmZ0eSkkLCBhbmQgJChyXzMgPSAxLCBkXzMgPSAwLCBsXzMgPSA2KSQuIAoKYGBge3J9CiMjIENoYXJhY3RlcmlzdGljcyBvZiB0aGUgcHVyZSBwcmVtaXVtIHdoaWNoIGRlcGVuZHMgb24gdGhlIHBhcmFtZXRlciBvZiB0aGUgaW5zdXJhbmNlIGNvdmVyYWdlCnBfcCA8LSBwdXJlX3ByZW1pdW0oInhzIiwgYygiciIsICJkIiwgImwiKSkKIyMgUmFuZG9tIHByZW1pdW0gcGFyYW1ldGVycwpuIDwtIDM7IHIgPC0gYygwLjc1LCAxLCAxKTsgZCA8LSBjKDAsIDEuOCwgMCk7IGwgPC0gYyhJbmYsIEluZiwgNikKCiMjIERhdGEgZnJhbWUgd2l0aCB0aGUgaW5zdXJhbmNlIGNvdmVyYWdlIHBhcmFtZXRlcnMgYW5kIHRoZSBwdXJlIHByZW1pdW0KdGhfcHJlbWl1bSA8LSBtYXRyaXgoYyhyLCBkLCBsKSwgbnJvdyA9IG4pCnBwcyA8LSBjb21wdXRlX3B1cmVfcHJlbWlhKFhfdHJ1ZSwgY292ZXJhZ2VfdHlwZSA9ICJ4cyIsIHRoX3ByZW1pdW0pCnNkcyA8LSBzZF9wdXJlX3ByZW1pYShYX3RydWUsIGNvdmVyYWdlX3R5cGUgPSAieHMiLCB0aF9wcmVtaXVtKQpkZl9wcCA8LSBkYXRhLmZyYW1lKHIgPSByLCBkID0gZCwgbCA9IGwsIHBwPXBwcykKZGZfcHAKYGBgClRoZSBwdXJlIHByZW1pdW0gY29tcHV0ZWQgYWJvdmUgY29ycmVzcG9uZHMgdG8gYSB3ZWxsIHNwZWNpZmllZCBjYXNlIHdoZXJlIHRoZXJlIGV4aXN0cyAkXHRoZXRhXiogPSBcdGhldGFfMCQgZm9yIHdoaWNoIAoKJCQKZFxsZWZ0W3BfezE6bn0scF97MTpufV57XHRoZXRhXntcYXN0fX1ccmlnaHRdID0gMAokJApOb3RlIHRoYXQgd2UgYXNzaWduIHRoZSBzYW1lIHdlaWdodCB0byBlYWNoIGlmIHRoZSBwcmUgcHJlbWl1bS4gV2UgY2FuIGNoZWNrIHRoZSB1bmlxdWVuZXNzIGVtcGlyaWNhbGx5LCBmaXJzdCBpbiBvbmUgZGltZW5zaW9uIGFzIHdlIHBsb3QgdGhlIGZ1bmN0aW9ucyAkXHNpZ21hXG1hcHN0byBkXGxlZnRbcF97MTpufSxwX3sxOm59XntcdGhldGFee1xhc3R9fVxyaWdodF1cQmlnXHJ2ZXJ0X3tcbXUgPTAsIFxsYW1iZGEgPSAzfSQsICRcbXVcbWFwc3RvIGRcbGVmdFtwX3sxOm59LHBfezE6bn1ee1x0aGV0YV57XGFzdH19XHJpZ2h0XVxCaWdccnZlcnRfe1xzaWdtYSA9MSwgXGxhbWJkYSA9IDN9JCwgYW5kICRcbGFtYmRhXG1hcHN0byBkXGxlZnRbcF97MTpufSxwX3sxOm59XntcdGhldGFee1xhc3R9fVxyaWdodF1cQmlnXHJ2ZXJ0X3tcbXUgPTAsIFxzaWdtYSA9IDF9JCAgCgpgYGB7cn0KZGF0YSA8LSBkZl9wcFssYygiciIsICJkIiwgImwiKV0KZGF0YVsieCJdIDwtIGRmX3BwJHBwCnRoc19wcmVtaXVtIDwtIGFzLm1hdHJpeChkYXRhW3BfcCRwYXJtX25hbWVzXSkKbGFtYmRhX3RydWUgPC0gMzsgbXVfdHJ1ZSA8LSAwOyBzaWdtYV90cnVlIDwtIDEKCiMgU2lnbWEgLS0tLS0tLS0tLS0tLS0KIyBQdXJlIHByZW1pdW0gY2FsY3VsYXRpb24gZm9yIGEgcmFuZ2Ugb2YgcmlzayBtb2RlbCBwYXJhbWV0ZXJzCnNpZ21hcyA8LSBzZXEoMC4xLCAyLCAwLjEpCmNsb3VkIDwtIGFzLm1hdHJpeChleHBhbmQuZ3JpZChjKDMpLCBjKDApLHNpZ21hcykpCmNvbG5hbWVzKGNsb3VkKSA8LSBsX20kcGFybV9uYW1lcwpYIDwtIHNhbXBsZV9YKGxfbSAsIGNsb3VkLCBSID0gMTAwMDApCnBwX2Zha2UgPC0gY29tcHV0ZV9wdXJlX3ByZW1pYShYLCBjb3ZlcmFnZV90eXBlID0gInhzIiwgdGhzX3ByZW1pdW0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAojIENhbGN1bGF0aW9uIG9mIHRoZSBSTVNFIGJldHdlZW4gdHJ1ZSBhbmQgd3JvbmcgcHVyZSBwcmVtaXVtCmRzIDwtIHNhcHBseSgxOm5yb3coY2xvdWQpLCBmdW5jdGlvbihrKSBtZWFuKChwcF9mYWtlWywga10gLSBkYXRhJHgpXjIpXigxLzIpKSAKZGZfZHMgPC0gZGF0YS5mcmFtZShjbG91ZCkKZGZfZHMgPC0gY2JpbmQoZGZfZHMsIGRzKQooc2lnX3B1cmVfUk1TRSA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2RzKSArIGdlb21fbGluZShtYXBwaW5nID0gYWVzKHggPSBzaWdtYSwgeSA9IGRzKSkgKyAgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNCkgKyBsYWJzKHggPSBleHByZXNzaW9uKHNpZ21hKSwgdGl0bGUgPSAiUk1TRSIsIHkgPSAiIikgKQpnZ3NhdmUoIi4uL2ZpZ3VyZXMvc2lnX3B1cmVfUk1TRS5wZGYiLCBzaWdfcHVyZV9STVNFKQoKIyBMYW1iZGEgLS0tLS0tLS0tLS0tLS0KbGFtYmRhcyA8LSBzZXEoMC4xLCA1LCAwLjEpCmNsb3VkIDwtIGFzLm1hdHJpeChleHBhbmQuZ3JpZChsYW1iZGFzLCBjKDApLGMoMSkpKQpjb2xuYW1lcyhjbG91ZCkgPC0gbF9tJHBhcm1fbmFtZXMKWCA8LSBzYW1wbGVfWChsX20gLCBjbG91ZCwgUiA9IDEwMDAwKQpwcF9mYWtlIDwtIGNvbXB1dGVfcHVyZV9wcmVtaWEoWCwgY292ZXJhZ2VfdHlwZSA9ICJ4cyIsIHRoc19wcmVtaXVtKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKIyBDYWxjdWxhdGlvbiBvZiB0aGUgUk1TRSBiZXR3ZWVuIHRydWUgYW5kIHdyb25nIHB1cmUgcHJlbWl1bQpkcyA8LSBzYXBwbHkoMTpucm93KGNsb3VkKSwgZnVuY3Rpb24oaykgbWVhbigocHBfZmFrZVssIGtdIC0gZGF0YSR4KV4yKV4oMS8yKSkgCmRmX2RzIDwtIGRhdGEuZnJhbWUoY2xvdWQpCmRmX2RzIDwtIGNiaW5kKGRmX2RzLCBkcykKKGxhbWJkYV9wdXJlX1JNU0UgPC0gZ2dwbG90KGRhdGEgPSBkZl9kcykgKyBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyh4ID0gbGFtYmRhLCB5ID0gZHMpKSArICBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE0KSArIGxhYnMoeCA9IGV4cHJlc3Npb24obGFtYmRhKSwgdGl0bGUgPSAiUk1TRSIsIHkgPSAiIikgKQpnZ3NhdmUoIi4uL2ZpZ3VyZXMvbGFtYmRhX3B1cmVfUk1TRS5wZGYiLCBsYW1iZGFfcHVyZV9STVNFKQoKIyBtdSAtLS0tLS0tLS0tLS0tLQptdXMgPC0gc2VxKC0zLCAzLCAwLjEpCmNsb3VkIDwtIGFzLm1hdHJpeChleHBhbmQuZ3JpZChjKDMpLCBtdXMsYygxKSkpCmNvbG5hbWVzKGNsb3VkKSA8LSBsX20kcGFybV9uYW1lcwpYIDwtIHNhbXBsZV9YKGxfbSAsIGNsb3VkLCBSID0gMTAwMDApCnBwX2Zha2UgPC0gY29tcHV0ZV9wdXJlX3ByZW1pYShYLCBjb3ZlcmFnZV90eXBlID0gInhzIiwgdGhzX3ByZW1pdW0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAojIENhbGN1bGF0aW9uIG9mIHRoZSBSTVNFIGJldHdlZW4gdHJ1ZSBhbmQgd3JvbmcgcHVyZSBwcmVtaXVtCmRzIDwtIHNhcHBseSgxOm5yb3coY2xvdWQpLCBmdW5jdGlvbihrKSBtZWFuKChwcF9mYWtlWywga10gLSBkYXRhJHgpXjIpXigxLzIpKSAKZGZfZHMgPC0gZGF0YS5mcmFtZShjbG91ZCkKZGZfZHMgPC0gY2JpbmQoZGZfZHMsIGRzKQoobXVfcHVyZV9STVNFIDwtIGdncGxvdChkYXRhID0gZGZfZHMpICsgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IG11LCB5ID0gZHMpKSArICBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE0KSArIGxhYnMoeCA9IGV4cHJlc3Npb24obXUpLCB0aXRsZSA9ICJSTVNFIiwgeSA9ICIiKSApCmdnc2F2ZSgiLi4vZmlndXJlcy9tdV9wdXJlX1JNU0UucGRmIiwgbXVfcHVyZV9STVNFKQpgYGAKRWFjaCBwYXJhbWV0ZXJzIGNhbiBiZSBpZGVudGlmaWVkIHNlcGFyYXRlbHksIG5vdyBvZiBjb3Vyc2UgaWRlbnRpZnlpbmcgdGhlbSBqb2ludGx5IGlzIGFub3RoZXIgbWF0dGVyLCB0aGVyZSBtaWdodCBleGlzdHMgc2V2ZXJhbCBjb21iaW5hdGlvbnMgb2YgcGFyYW1ldGVycyB0aGF0IHlpZWxkIHRoZSBzYW1lIHB1cmUgcHJlbWl1bS4gT3VyIG9wdGltaXphdGlvbiBhbGxvd3MgdXMgdG8gaW52ZXN0aWdhdGUgYnkgc2VhcmNoaW5nIGVmZmljaWVudGx5IHRoZSBwYXJhbWV0ZXIgc3BhY2UuIAoKV2UgdXNlIHRoZSBmb2xsd2luZyBwcmlvciBhc3N1bXB0aW9uczoKJCQKXGxhbWJkYVxzaW1cdGV4dHtVbmlmfSgwLCAxMClcdGV4dHssIH1cbXVcc2ltXHRleHR7VW5pZn0oLTMsIDMpXHRleHR7LCBhbmQgfVxzaWdtYVxzaW1cdGV4dHtVbmlmfSgwLCA1KQokJAphbmQgdGhlIGZvbGxvd2luZyBzZXR0aW5ncyBmb3IgdGhlIGFsZ29yaXRobQoKJCQKSiA9IDUwMFx0ZXh0eyBhbmQgfVIgPSA1MDAKJCQKUmVjYWxsIHRoYXQgJEokIGlzIHRoZSBwb3B1bGF0aW9uIHNpemUgb2YgdGhlIGNsb3VkcyBvZiBwYXJ0aWNsZXMgYW5kICRSJCBpcyB0aGUgbnVtYmVyIG9mIE1vbnRlIENhcmxvIHJlcGxpY2F0aW9ucy4gCgpgYGB7cn0KIyBQcmlvciBzZXR0aW5ncyBmb3IgdGhlIHBhcmFtZXRlcnMKcHJpb3JfbGFtYmRhIDwtIHByaW9yX2Rpc3QoInVuaWZvcm0iLCAibGFtYmRhIixjKDAsIDEwKSkKcHJpb3JfbXUgPC0gcHJpb3JfZGlzdCgidW5pZm9ybSIsICJtdSIsYygtMywzKSkKcHJpb3Jfc2lnbWEgPC0gcHJpb3JfZGlzdCgidW5pZm9ybSIsICJzaWdtYSIsIGMoMCwgNSkpCnByaW9yX2Rpc3RyaWJ1dGlvbnMgPC0gbGlzdChwcmlvcl9sYW1iZGEsIHByaW9yX211LCBwcmlvcl9zaWdtYSkKbW9kZWxfcHJpb3IgPC0gaW5kZXBlbmRlbnRfcHJpb3JzKHByaW9yX2Rpc3RyaWJ1dGlvbnMpCgojIFNldHRpbmdzIGZvciB0aGUgYWJjIGFsZ29yaXRobQpwb3BTaXplIDwtIDUwMDsgIE1DX1I8LSA1MDA7IGFjYyA8LSAxMDsgc3BfYm91bmRzIDwtIGMoMSwgMSk7IGVwc19taW4gPC0gMC4wMgoKc3VtKHNkcy9zcXJ0KE1DX1IpXjIpCgpkYXRhIDwtIGRmX3BwWyxjKCJyIiwgImQiLCAibCIpXQpkYXRhWyJ4Il0gPC0gZGZfcHAkcHAKIyByZXNfYWJjIDwtIGFiYyhkYXRhLCBtb2RlbF9wcmlvciwgbF9tLCBwX3AsIHBvcFNpemUsIE1DX1IsIGFjYywgc3BfYm91bmRzLCBlcHNfbWluKQojIHNhdmUocmVzX2FiYywgZmlsZSA9ICIuLi9kYXRhL3Jlc19hYmNfc3VwcF9tYXRlcmlhbF9TZWN0aW9uMS5SRGF0YSIpCmBgYAoKYGBge3J9CmxvYWQoIi4uL2RhdGEvcmVzX2FiY19zdXBwX21hdGVyaWFsX1NlY3Rpb24xLlJEYXRhIikKIyBXZSByZXRyaWV2ZSB0aGUgY2xvdWQgb2YgcGFydGljbGVzIGFzc29jaWF0ZWQgdG8gZWFjaCBnZW5lcmF0aW9uCmNsb3VkX2RmcyA8LSBsYXBwbHkocmVzX2FiYyRDbG91ZHMsIGFzLmRhdGEuZnJhbWUpCmNsb3VkX2RmIDwtIGRvLmNhbGwocmJpbmQsIGNsb3VkX2RmcykKY2xvdWRfZGYkZ2VuZXJhdGlvbiA8LSBzb3J0KHJlcCgxOmxlbmd0aChyZXNfYWJjJENsb3VkcyksIHBvcFNpemUpKQpjbG91ZF9kZl9wbG90IDwtIHJiaW5kKAogIGRhdGEuZnJhbWUocGFybSA9IGNsb3VkX2RmJGxhbWJkYSwgcGFybV9uYW1lID0gImxhbWJkYSIsIGdlbmVyYXRpb24gPSBjbG91ZF9kZiRnZW5lcmF0aW9uKSwKICBkYXRhLmZyYW1lKHBhcm0gPSBjbG91ZF9kZiRzaWdtYSwgcGFybV9uYW1lID0gInNpZ21hIiwgZ2VuZXJhdGlvbiA9IGNsb3VkX2RmJGdlbmVyYXRpb24pCikKY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUgPC1hcy5mYWN0b3IoY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUpIApsZXZlbHMoY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUpIDwtIGMobGFtYmRhID0gVGVYKCIkXFxsYW1iZGEkIiksIHNpZ21hID0gVGVYKCIkXFxzaWdtYSQiKSkKCihwb3N0ZXJpb3JfbGFtYmRhIDwtIGdncGxvdDI6OmdncGxvdChkYXRhID0gY2xvdWRfZGYgKSArIGdncGxvdDI6Omdlb21fZGVuc2l0eShkYXRhID0gY2xvdWRfZGYsIG1hcHBpbmcgPSBhZXMoeD1sYW1iZGEsIGNvbG9yID0gYXMuZmFjdG9yKGdlbmVyYXRpb24pKSkgKyBnZ3Bsb3QyOjpsYWJzKHg9VGVYKCIkXFxsYW1iZGEkIiksIHkgPSAiRGVuc2l0eSIsIGNvbG9yID0gIkdlbmVyYXRpb24iKSArIGdncGxvdDI6OnRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMjApICsgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsgZ2dwbG90Mjo6Z2VvbV92bGluZShnZ3Bsb3QyOjphZXMoeGludGVyY2VwdD10cnVlX3Bhcm1zWywxXSksIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpKQpnZ3NhdmUoIi4uL2ZpZ3VyZXMvcG9zdGVyaW9yX2xhbWJkYV9zdXBwX21hdC5wZGYiLCBwb3N0ZXJpb3JfbGFtYmRhKQoKKHBvc3Rlcmlvcl9tdSA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoZGF0YSA9IGNsb3VkX2RmICkgKyBnZ3Bsb3QyOjpnZW9tX2RlbnNpdHkoZGF0YSA9IGNsb3VkX2RmLCBtYXBwaW5nID0gYWVzKHg9bXUsIGNvbG9yID0gYXMuZmFjdG9yKGdlbmVyYXRpb24pKSkgKyBnZ3Bsb3QyOjpsYWJzKHg9VGVYKCIkXFxtdSQiKSwgeSA9ICJEZW5zaXR5IiwgY29sb3IgPSAiR2VuZXJhdGlvbiIpICsgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAyMCkgKyBnZ3Bsb3QyOjp0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKyBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKGdncGxvdDI6OmFlcyh4aW50ZXJjZXB0PXRydWVfcGFybXNbLDJdKSwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIikpCmdnc2F2ZSgiLi4vZmlndXJlcy9wb3N0ZXJpb3JfbXVfc3VwcF9tYXQucGRmIiwgcG9zdGVyaW9yX211KQoKKHBvc3Rlcmlvcl9zaWcgPC0gZ2dwbG90Mjo6Z2dwbG90KGRhdGEgPSBjbG91ZF9kZiApICsgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGRhdGEgPSBjbG91ZF9kZiwgbWFwcGluZyA9IGFlcyh4PXNpZ21hLCBjb2xvciA9IGFzLmZhY3RvcihnZW5lcmF0aW9uKSkpICsgZ2dwbG90Mjo6bGFicyh4PVRlWCgiJFxcc2lnbWEkIiksIHkgPSAiRGVuc2l0eSIsIGNvbG9yID0gIkdlbmVyYXRpb24iKSArIGdncGxvdDI6OnRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMjApICsgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsgZ2dwbG90Mjo6Z2VvbV92bGluZShnZ3Bsb3QyOjphZXMoeGludGVyY2VwdD10cnVlX3Bhcm1zWywzXSksIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpKQpnZ3NhdmUoIi4uL2ZpZ3VyZXMvcG9zdGVyaW9yX3NpZ19zdXBwX21hdC5wZGYiLCBwb3N0ZXJpb3Jfc2lnKQoKYGBgCgojIElJIC0gT3B0aW1pemF0aW9uIGJhc2VkIG9uIHRoZSBjb21tZXJjaWFsIHByZW1pdW1zIHdpdGhvdXQgcmVndWxhcml6YXRpb24KCldlIGRvIG5vdCBoYXZlIGFjY2VzcyB0byB0aGUgcHVyZSBwcmVtaXVtLCBpbnN0ZWFkIHdlIGhhdmUgdGhlIGNvbW1lcmNpYWwgcHJlbWl1bXMKCiQkClx0aWxkZXtwfV9pID0gZl9pXGxlZnRbXG1hdGhiYntFfShnX2koWCkpXHJpZ2h0XSxcdGV4dHsgfWkgPSAxLFxsZG90cywgbiwKJCQKCndoZXJlIHRoZSBsb2FkaW5nIGZ1bmN0aW9ucyBtdXN0IGJlIGFwcHJveGltYXRlZC4gV2UgdGhlcmVmb3JlIGhhdmUgdG8gY2hvb3NlIGEgbW9kZWwgJGYkIHN1Y2ggdGhhdCAKCiQkClx0aWxkZXtwfV9pID0gZihwX3tpfV5cdGhldGEpLFx0ZXh0eyB9aSA9IDEsXGxkb3RzLCBuICAKJCQKYW5kIGhvcGUgdGhhdCB0aGVyZSBleGlzdHMgYSB1bmlxdWUgJFx0aGV0YV4qJCBzdWNoIHRoYXQgCgokJApcdGhldGFeKiA9IFx1bmRlcnNldHtcdGhldGFcaW4gXFRoZXRhfXtcdGV4dHthcmdtaW59fVwsIGRcbGVmdFtcdGlsZGV7cH1fezE6bn0sZihwX3sxOm59Xlx0aGV0YSlccmlnaHRdLgokJApUaGlzIHR5cGljYWxseSBkZXBlbmRzIG9uIHRoZSBjaG9pY2UgZm9yICRmJCB3ZSBjb25zaWRlciBpc290b25pYyBhbmQgbGluZWFyLiBJc290b25pYyByZWdyZXNzaW9uIGltcG9zZSBtb25vdG9uaWNpdHkgd2hpY2ggaXMgZGVzaXJhYmxlIHNpbmNlIHdlIGJlbGlldmUgaXQgd291bGQgbWFrZSBzZW5zZSBpZiAKCiQkCnBfaSA+IHBfalxSaWdodGFycm93IFx0aWxkZXtwfV9pID4gXHRpbGRle3B9X2ouCiQkCgpGdXJ0aGVybW9yZSBpc290b25pYyByZWdyZXNzaW9uIGlzIG5vbiBwYXJhbWV0cmljIHdoaWNoIG1pdGlnYXRlIHRoZSByaXNrIG9mIG1pc3NwZWNpZmljYXRpb24uIFRoZSBkcmF3YmFjayBpcyBvdmVyZml0dGluZyBhcyBwZXJmZWN0IGludGVycG9sYXRpb24gb2YgbWF5IG9jY3VyIGluIGEgc21hbGwgc2FtcGxlIHNpemUgc2V0dGluZy4gCgojIyBXZWxsLXNwZWNpZmllZCBjYXNlCgpJbiBvdXIgZXhhbXBsZSB3ZSB0YWtlIHRoZSBmb2xsb3dpbmcgbG9hZGluZyBmdXVuY3Rpb25zIAoKJCQKZl8xKHgpID0gMS4xXGNkb3QgeFx0ZXh0eywgfWZfMih4KSA9IDEuMlxjZG90IHggXHRleHR7LCBhbmQgfSBmXzMoeCkgPSAxLjNcY2RvdCB4CiQkCgpgYGB7cn0KZGF0YSA8LSBkZl9wcFssYygiciIsICJkIiwgImwiKV0KZGF0YVsieCJdIDwtIGMoZGZfcHAkcHBbMV0qMS4zOCAsIGRmX3BwJHBwWzJdKjEuMSAsIGRmX3BwJHBwWzNdICogMS40ICkKIyBkYXRhWyJ4Il0gPC0gZGZfcHAkcHAKdGhzX3ByZW1pdW0gPC0gYXMubWF0cml4KGRhdGFbcF9wJHBhcm1fbmFtZXNdKQpsYW1iZGFfdHJ1ZSA8LSAzOyBtdV90cnVlIDwtIDA7IHNpZ21hX3RydWUgPC0gMQoocHBfY3Bfd2VsbF9zcGVjaWZpZWQgPC0gZ2dwbG90KCkgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRmX3BwJHBwLCB5ID0gZGF0YSR4KSkgKyAgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNCkgKyBsYWJzKHggPSAiUHVyZSBQcmVtaXVtIiwgdGl0bGUgPSAiQ29tbWVyY2lhbCBwcmVtaXVtIiwgeSA9ICIiKSApCmdnc2F2ZSgiLi4vZmlndXJlcy9wcF9jcF93ZWxsX3NwZWNpZmllZC5wZGYiLCBwcF9jcF93ZWxsX3NwZWNpZmllZCkKYGBgCgpgYGB7cn0KIyBTaWdtYSAtLS0tLS0tLS0tLS0tLQojIFB1cmUgcHJlbWl1bSBjYWxjdWxhdGlvbiBmb3IgYSByYW5nZSBvZiByaXNrIG1vZGVsIHBhcmFtZXRlcnMKc2lnbWFzIDwtIHNlcSgwLjEsIDIsIDAuMDIpCmNsb3VkIDwtIGFzLm1hdHJpeChleHBhbmQuZ3JpZChjKDMpLCBjKDApLHNpZ21hcykpCmNvbG5hbWVzKGNsb3VkKSA8LSBsX20kcGFybV9uYW1lcwpYIDwtIHNhbXBsZV9YKGxfbSAsIGNsb3VkLCBSID0gMTAwMDApCnBwX2Zha2UgPC0gY29tcHV0ZV9wdXJlX3ByZW1pYShYLCBjb3ZlcmFnZV90eXBlID0gInhzIiwgdGhzX3ByZW1pdW0pCiMgQ2FsY3VsYXRpb24gb2YgdGhlIFJNU0UgYmV0d2VlbiB0cnVlIGFuZCB3cm9uZyBjb21tZXJjaWFsIHByZW1pdW0KcmVzc19pc28gPC0gbGFwcGx5KDE6bmNvbChwcF9mYWtlKSwgZnVuY3Rpb24oaykgaXNvcmVnKHBwX2Zha2VbLCBrXSwgZGF0YSR4KSkKCnJlc3NfbG0gPC0gc2FwcGx5KDE6bmNvbChwcF9mYWtlKSwgZnVuY3Rpb24oaykgYXMubnVtZXJpYyhsbShkYXRhJHh+cHBfZmFrZVssIGtdIC0gMSkkY29lZmZpY2llbnRzKSkKcmVzc19sbVtzaWdtYXMgPT0gMV0KYXMubnVtZXJpYyhsbShkYXRhJHggfiBwcF9mYWtlWywgc2lnbWFzID09IDFdIC0gMSkkY29lZmZpY2llbnRzKQptZWFuKChtZWFuKChwcF9mYWtlWywgc2lnbWFzID09IDFdICogcmVzc19sbVtzaWdtYXMgPT0gMV0gLSBkYXRhJHgpXjIpXigxLzIpIC0gZGF0YSR4KV4yKV4oMS8yKQpmc19pc28gPC0gbGFwcGx5KHJlc3NfaXNvLCBmdW5jdGlvbihyZXNfaXNvKSBzdGVwZnVuKHNvcnQocmVzX2lzbyR4KSwgYyhtaW4ocmVzX2lzbyR5ZikgLzIgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzX2lzbyR5ZiksIGYgPSAxKSkKZHNfaXNvIDwtIHNhcHBseSgxOm5yb3coY2xvdWQpLCBmdW5jdGlvbihrKSBtZWFuKChmc19pc29bW2tdXShwcF9mYWtlWywga10pIC0gZGF0YSR4KV4yKV4oMS8yKSkgCmRzX2xtIDwtIHNhcHBseSgxOm5yb3coY2xvdWQpLCBmdW5jdGlvbihrKSBtZWFuKChwcF9mYWtlWywga10gLyByZXNzX2xtW2tdIC0gZGF0YSR4KV4yKV4oMS8yKSkgCgpkZl9kcyA8LSBkYXRhLmZyYW1lKGNsb3VkKQpkZl9kcyA8LSBjYmluZChkZl9kcywgZHNfaXNvKQpkZl9kcyA8LSBjYmluZChkZl9kcywgZHNfbG0pCmdncGxvdChkYXRhID0gZGZfZHMpICsgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IHNpZ21hLCB5ID0gZHNfaXNvKSkKZ2dwbG90KGRhdGEgPSBkZl9kcykgKyBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyh4ID0gc2lnbWEsIHkgPSBkc19sbSkpCgpzaWdtYXNbZHNfbG0gPT0gbWluKGRzX2xtKV0KYGBgCgoKYGBge3J9CiMgUHJpb3Igc2V0dGluZ3MgZm9yIHRoZSBwYXJhbWV0ZXJzCnByaW9yX2xhbWJkYSA8LSBwcmlvcl9kaXN0KCJ1bmlmb3JtIiwgImxhbWJkYSIsYygwLCA1KSkKcHJpb3JfbXUgPC0gcHJpb3JfZGlzdCgidW5pZm9ybSIsICJtdSIsYygtMywzKSkKcHJpb3Jfc2lnbWEgPC0gcHJpb3JfZGlzdCgidW5pZm9ybSIsICJzaWdtYSIsIGMoMCwgMikpCnByaW9yX2Rpc3RyaWJ1dGlvbnMgPC0gbGlzdChwcmlvcl9sYW1iZGEsIHByaW9yX211LCBwcmlvcl9zaWdtYSkKbW9kZWxfcHJpb3IgPC0gaW5kZXBlbmRlbnRfcHJpb3JzKHByaW9yX2Rpc3RyaWJ1dGlvbnMpCgojIFNldHRpbmdzIGZvciB0aGUgYWJjIGFsZ29yaXRobQpwb3BTaXplIDwtIDUwMDsgIE1DX1I8LSA1MDA7IGFjYyA8LSAwLjAxOyBzcF9ib3VuZHMgPC0gYygxMF4oLTE2KSwgSW5mKTsgZXBzX21pbiA8LSAwLjAxCnJlc19hYmMgPC0gYWJjKGRhdGEsIG1vZGVsX3ByaW9yLCBsX20sIHBfcCwgcG9wU2l6ZSwgTUNfUiwgYWNjLCBzcF9ib3VuZHMsIGVwc19taW4pCmBgYAoKYGBge3J9CiMgV2UgcmV0cmlldmUgdGhlIGNsb3VkIG9mIHBhcnRpY2xlcyBhc3NvY2lhdGVkIHRvIGVhY2ggZ2VuZXJhdGlvbgpjbG91ZF9kZnMgPC0gbGFwcGx5KHJlc19hYmMkQ2xvdWRzLCBhcy5kYXRhLmZyYW1lKQpjbG91ZF9kZiA8LSBkby5jYWxsKHJiaW5kLCBjbG91ZF9kZnMpCmNsb3VkX2RmJGdlbmVyYXRpb24gPC0gc29ydChyZXAoMTpsZW5ndGgocmVzX2FiYyRDbG91ZHMpLCBwb3BTaXplKSkKY2xvdWRfZGZfcGxvdCA8LSByYmluZCgKICBkYXRhLmZyYW1lKHBhcm0gPSBjbG91ZF9kZiRsYW1iZGEsIHBhcm1fbmFtZSA9ICJsYW1iZGEiLCBnZW5lcmF0aW9uID0gY2xvdWRfZGYkZ2VuZXJhdGlvbiksCiAgZGF0YS5mcmFtZShwYXJtID0gY2xvdWRfZGYkc2lnbWEsIHBhcm1fbmFtZSA9ICJzaWdtYSIsIGdlbmVyYXRpb24gPSBjbG91ZF9kZiRnZW5lcmF0aW9uKQopCmNsb3VkX2RmX3Bsb3QkcGFybV9uYW1lIDwtYXMuZmFjdG9yKGNsb3VkX2RmX3Bsb3QkcGFybV9uYW1lKSAKbGV2ZWxzKGNsb3VkX2RmX3Bsb3QkcGFybV9uYW1lKSA8LSBjKGxhbWJkYSA9IFRlWCgiJFxcbGFtYmRhJCIpLCBzaWdtYSA9IFRlWCgiJFxcc2lnbWEkIikpCmdncGxvdDI6OmdncGxvdChkYXRhID0gY2xvdWRfZGYgKSArIGdncGxvdDI6Omdlb21fZGVuc2l0eShkYXRhID0gY2xvdWRfZGYsIG1hcHBpbmcgPSBhZXMoeD1sYW1iZGEsIGNvbG9yID0gYXMuZmFjdG9yKGdlbmVyYXRpb24pKSkgKyBnZ3Bsb3QyOjpsYWJzKHg9VGVYKCIkXFxsYW1iZGEkIiksIHkgPSAiRGVuc2l0eSIsIGNvbG9yID0gIkdlbmVyYXRpb24iKSArIGdncGxvdDI6OnRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMjApICsgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsgZ2dwbG90Mjo6Z2VvbV92bGluZShnZ3Bsb3QyOjphZXMoeGludGVyY2VwdD10cnVlX3Bhcm1zWywxXSksIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpCgpnZ3Bsb3QyOjpnZ3Bsb3QoZGF0YSA9IGNsb3VkX2RmICkgKyBnZ3Bsb3QyOjpnZW9tX2RlbnNpdHkoZGF0YSA9IGNsb3VkX2RmLCBtYXBwaW5nID0gYWVzKHg9bXUsIGNvbG9yID0gYXMuZmFjdG9yKGdlbmVyYXRpb24pKSkgKyBnZ3Bsb3QyOjpsYWJzKHg9VGVYKCIkXFxtdSQiKSwgeSA9ICJEZW5zaXR5IiwgY29sb3IgPSAiR2VuZXJhdGlvbiIpICsgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAyMCkgKyBnZ3Bsb3QyOjp0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKyBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKGdncGxvdDI6OmFlcyh4aW50ZXJjZXB0PXRydWVfcGFybXNbLDJdKSwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIikKCmdncGxvdDI6OmdncGxvdChkYXRhID0gY2xvdWRfZGYgKSArIGdncGxvdDI6Omdlb21fZGVuc2l0eShkYXRhID0gY2xvdWRfZGYsIG1hcHBpbmcgPSBhZXMoeD1zaWdtYSwgY29sb3IgPSBhcy5mYWN0b3IoZ2VuZXJhdGlvbikpKSArIGdncGxvdDI6OmxhYnMoeD1UZVgoIiRcXHNpZ21hJCIpLCB5ID0gIkRlbnNpdHkiLCBjb2xvciA9ICJHZW5lcmF0aW9uIikgKyBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDIwKSArIGdncGxvdDI6OnRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKSArIGdncGxvdDI6Omdlb21fdmxpbmUoZ2dwbG90Mjo6YWVzKHhpbnRlcmNlcHQ9dHJ1ZV9wYXJtc1ssM10pLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiKQpgYGAKIyBJSUkgLSBPcHRpbWl6YXRpb24gYmFzZWQgb24gdGhlIGNvbW1lcmNpYWwgcHJlbWl1bXMgd2l0aCByZWd1bGFyaXphdGlvbgoKCmBgYHtyfQojIEFkZGluZyB0aGUgcmVndWxhcml6YXRpb24gdGVybXMKc3BfYm91bmRzIDwtIGMobWluKGRmX3BwJHBwIC8gZGF0YSR4KSwgbWF4KGRmX3BwJHBwIC8gZGF0YSR4KSkKIyBzcF9ib3VuZHMgPC0gYygwLjYsIDAuOTUpCmRzMSA8LSBzYXBwbHkoMTpuY29sKHBwX2Zha2UpLCBmdW5jdGlvbihrKSBzcXJ0KG1lYW4oKHBtYXgoZGF0YSR4IC0gcHBfZmFrZVssa10gL3NwX2JvdW5kc1sxXSwgMCkgKV4yKSkpCmRzMiA8LSBzYXBwbHkoMTpuY29sKHBwX2Zha2UpLCBmdW5jdGlvbihrKSBzcXJ0KG1lYW4oKHBtYXgoIHBwX2Zha2VbLGtdIC8gc3BfYm91bmRzWzJdIC0gZGF0YSR4ICwgMCkgKV4yKSkpCmRzX2lzb19yZWcgPC0gZHNfaXNvICsgZHMxICsgZHMyCmRzX2xtX3JlZyA8LSBkc19sbSArIGRzMSArIGRzMgpkZl9kcyA8LSBkYXRhLmZyYW1lKGNsb3VkKQpkZl9kcyA8LSBjYmluZChkZl9kcywgZHNfaXNvX3JlZywgZHNfbG1fcmVnKQpnZ3Bsb3QoZGF0YSA9IGRmX2RzKSArIGdlb21fbGluZShtYXBwaW5nID0gYWVzKHggPSBzaWdtYSwgeSA9IGRzX2lzb19yZWcpKQpnZ3Bsb3QoZGF0YSA9IGRmX2RzKSArIGdlb21fbGluZShtYXBwaW5nID0gYWVzKHggPSBzaWdtYSwgeSA9IGRzX2xtX3JlZykpCnByaW50KHNpZ21hc1tkc19sbV9yZWc9PW1pbihkc19sbV9yZWcpXSkKcHJpbnQoc2lnbWFzW2RzX2lzb19yZWc9PW1pbihkc19pc29fcmVnKV0pCmBgYApgYGB7cn0KIyBQcmlvciBzZXR0aW5ncyBmb3IgdGhlIHBhcmFtZXRlcnMKcHJpb3JfbGFtYmRhIDwtIHByaW9yX2Rpc3QoInVuaWZvcm0iLCAibGFtYmRhIixjKDAsIDUpKQpwcmlvcl9tdSA8LSBwcmlvcl9kaXN0KCJ1bmlmb3JtIiwgIm11IixjKC0zLDMpKQpwcmlvcl9zaWdtYSA8LSBwcmlvcl9kaXN0KCJ1bmlmb3JtIiwgInNpZ21hIiwgYygwLCAyKSkKcHJpb3JfZGlzdHJpYnV0aW9ucyA8LSBsaXN0KHByaW9yX2xhbWJkYSwgcHJpb3JfbXUsIHByaW9yX3NpZ21hKQptb2RlbF9wcmlvciA8LSBpbmRlcGVuZGVudF9wcmlvcnMocHJpb3JfZGlzdHJpYnV0aW9ucykKCiMgU2V0dGluZ3MgZm9yIHRoZSBhYmMgYWxnb3JpdGhtCnBvcFNpemUgPC0gNTAwOyAgTUNfUjwtIDUwMDsgYWNjIDwtIDAuMDAxOyBzcF9ib3VuZHMgPC0gYyhtaW4oZGZfcHAkcHAgLyBkYXRhJHgpLCBtYXgoZGZfcHAkcHAgLyBkYXRhJHgpKQplcHNfbWluIDwtIDAuMDAwMQpyZXNfYWJjIDwtIGFiYyhkYXRhLCBtb2RlbF9wcmlvciwgbF9tLCBwX3AsIHBvcFNpemUsIE1DX1IsIGFjYywgc3BfYm91bmRzLCBlcHNfbWluKQpgYGAKCmBgYHtyfQojIFdlIHJldHJpZXZlIHRoZSBjbG91ZCBvZiBwYXJ0aWNsZXMgYXNzb2NpYXRlZCB0byBlYWNoIGdlbmVyYXRpb24KY2xvdWRfZGZzIDwtIGxhcHBseShyZXNfYWJjJENsb3VkcywgYXMuZGF0YS5mcmFtZSkKY2xvdWRfZGYgPC0gZG8uY2FsbChyYmluZCwgY2xvdWRfZGZzKQpjbG91ZF9kZiRnZW5lcmF0aW9uIDwtIHNvcnQocmVwKDE6bGVuZ3RoKHJlc19hYmMkQ2xvdWRzKSwgcG9wU2l6ZSkpCmNsb3VkX2RmX3Bsb3QgPC0gcmJpbmQoCiAgZGF0YS5mcmFtZShwYXJtID0gY2xvdWRfZGYkbGFtYmRhLCBwYXJtX25hbWUgPSAibGFtYmRhIiwgZ2VuZXJhdGlvbiA9IGNsb3VkX2RmJGdlbmVyYXRpb24pLAogIGRhdGEuZnJhbWUocGFybSA9IGNsb3VkX2RmJHNpZ21hLCBwYXJtX25hbWUgPSAic2lnbWEiLCBnZW5lcmF0aW9uID0gY2xvdWRfZGYkZ2VuZXJhdGlvbikKKQpjbG91ZF9kZl9wbG90JHBhcm1fbmFtZSA8LWFzLmZhY3RvcihjbG91ZF9kZl9wbG90JHBhcm1fbmFtZSkgCmxldmVscyhjbG91ZF9kZl9wbG90JHBhcm1fbmFtZSkgPC0gYyhsYW1iZGEgPSBUZVgoIiRcXGxhbWJkYSQiKSwgc2lnbWEgPSBUZVgoIiRcXHNpZ21hJCIpKQpnZ3Bsb3QyOjpnZ3Bsb3QoZGF0YSA9IGNsb3VkX2RmICkgKyBnZ3Bsb3QyOjpnZW9tX2RlbnNpdHkoZGF0YSA9IGNsb3VkX2RmLCBtYXBwaW5nID0gYWVzKHg9bGFtYmRhLCBjb2xvciA9IGFzLmZhY3RvcihnZW5lcmF0aW9uKSkpICsgZ2dwbG90Mjo6bGFicyh4PVRlWCgiJFxcbGFtYmRhJCIpLCB5ID0gIkRlbnNpdHkiLCBjb2xvciA9ICJHZW5lcmF0aW9uIikgKyBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDIwKSArIGdncGxvdDI6OnRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKSArIGdncGxvdDI6Omdlb21fdmxpbmUoZ2dwbG90Mjo6YWVzKHhpbnRlcmNlcHQ9dHJ1ZV9wYXJtc1ssMV0pLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiKQoKZ2dwbG90Mjo6Z2dwbG90KGRhdGEgPSBjbG91ZF9kZiApICsgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGRhdGEgPSBjbG91ZF9kZiwgbWFwcGluZyA9IGFlcyh4PW11LCBjb2xvciA9IGFzLmZhY3RvcihnZW5lcmF0aW9uKSkpICsgZ2dwbG90Mjo6bGFicyh4PVRlWCgiJFxcbXUkIiksIHkgPSAiRGVuc2l0eSIsIGNvbG9yID0gIkdlbmVyYXRpb24iKSArIGdncGxvdDI6OnRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMjApICsgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsgZ2dwbG90Mjo6Z2VvbV92bGluZShnZ3Bsb3QyOjphZXMoeGludGVyY2VwdD10cnVlX3Bhcm1zWywyXSksIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpCgpnZ3Bsb3QyOjpnZ3Bsb3QoZGF0YSA9IGNsb3VkX2RmICkgKyBnZ3Bsb3QyOjpnZW9tX2RlbnNpdHkoZGF0YSA9IGNsb3VkX2RmLCBtYXBwaW5nID0gYWVzKHg9c2lnbWEsIGNvbG9yID0gYXMuZmFjdG9yKGdlbmVyYXRpb24pKSkgKyBnZ3Bsb3QyOjpsYWJzKHg9VGVYKCIkXFxzaWdtYSQiKSwgeSA9ICJEZW5zaXR5IiwgY29sb3IgPSAiR2VuZXJhdGlvbiIpICsgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAyMCkgKyBnZ3Bsb3QyOjp0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKyBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKGdncGxvdDI6OmFlcyh4aW50ZXJjZXB0PXRydWVfcGFybXNbLDNdKSwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIikKCnJlc19hYmMkZHNbWzEzXV0KYGBgCgojIyBXZWxsLXNwZWNpZmllZCBjYXNlCgpJbiBvdXIgZXhhbXBsZSB3ZSB0YWtlIHRoZSBmb2xsb3dpbmcgbG9hZGluZyBmdXVuY3Rpb25zIAoKJCQKZl8xKHgpID0gMS4xXGNkb3QgeFx0ZXh0eywgfWZfMih4KSA9IDEuMlxjZG90IHggXHRleHR7LCBhbmQgfSBmXzMoeCkgPSAxLjNcY2RvdCB4CiQkCgpgYGB7cn0KZGF0YSA8LSBkZl9wcFssYygiciIsICJkIiwgImwiKV0KZGF0YVsieCJdIDwtIGMoZGZfcHAkcHBbMV0qMS4xICwgZGZfcHAkcHBbMl0qMS4yICwgZGZfcHAkcHBbM10gKiAxLjMgKQojIGRhdGFbIngiXSA8LSBkZl9wcCRwcAp0aHNfcHJlbWl1bSA8LSBhcy5tYXRyaXgoZGF0YVtwX3AkcGFybV9uYW1lc10pCmxhbWJkYV90cnVlIDwtIDM7IG11X3RydWUgPC0gMDsgc2lnbWFfdHJ1ZSA8LSAxCihwcF9jcF93ZWxsX3NwZWNpZmllZCA8LSBnZ3Bsb3QoKSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGZfcHAkcHAsIHkgPSBkYXRhJHgpKSArICBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE0KSArIGxhYnMoeCA9ICJQdXJlIFByZW1pdW0iLCB0aXRsZSA9ICJDb21tZXJjaWFsIHByZW1pdW0iLCB5ID0gIiIpICkKZ2dzYXZlKCIuLi9maWd1cmVzL3BwX2NwX3dlbGxfc3BlY2lmaWVkLnBkZiIsIHBwX2NwX3dlbGxfc3BlY2lmaWVkKQpgYGAKCmBgYHtyfQojIFNpZ21hIC0tLS0tLS0tLS0tLS0tCiMgUHVyZSBwcmVtaXVtIGNhbGN1bGF0aW9uIGZvciBhIHJhbmdlIG9mIHJpc2sgbW9kZWwgcGFyYW1ldGVycwpzaWdtYXMgPC0gc2VxKDAuMSwgMiwgMC4wMikKY2xvdWQgPC0gYXMubWF0cml4KGV4cGFuZC5ncmlkKGMoMyksIGMoMCksc2lnbWFzKSkKY29sbmFtZXMoY2xvdWQpIDwtIGxfbSRwYXJtX25hbWVzClggPC0gc2FtcGxlX1gobF9tICwgY2xvdWQsIFIgPSAxMDAwMCkKcHBfZmFrZSA8LSBjb21wdXRlX3B1cmVfcHJlbWlhKFgsIGNvdmVyYWdlX3R5cGUgPSAieHMiLCB0aHNfcHJlbWl1bSkKIyBDYWxjdWxhdGlvbiBvZiB0aGUgUk1TRSBiZXR3ZWVuIHRydWUgYW5kIHdyb25nIGNvbW1lcmNpYWwgcHJlbWl1bQpyZXNzX2lzbyA8LSBsYXBwbHkoMTpuY29sKHBwX2Zha2UpLCBmdW5jdGlvbihrKSBpc29yZWcocHBfZmFrZVssIGtdLCBkYXRhJHgpKQoKcmVzc19sbSA8LSBzYXBwbHkoMTpuY29sKHBwX2Zha2UpLCBmdW5jdGlvbihrKSBhcy5udW1lcmljKGxtKGRhdGEkeH5wcF9mYWtlWywga10gLSAxKSRjb2VmZmljaWVudHMpKQpyZXNzX2xtW3NpZ21hcyA9PSAxXQphcy5udW1lcmljKGxtKGRhdGEkeCB+IHBwX2Zha2VbLCBzaWdtYXMgPT0gMV0gLSAxKSRjb2VmZmljaWVudHMpCm1lYW4oKG1lYW4oKHBwX2Zha2VbLCBzaWdtYXMgPT0gMV0gKiByZXNzX2xtW3NpZ21hcyA9PSAxXSAtIGRhdGEkeCleMileKDEvMikgLSBkYXRhJHgpXjIpXigxLzIpCmZzX2lzbyA8LSBsYXBwbHkocmVzc19pc28sIGZ1bmN0aW9uKHJlc19pc28pIHN0ZXBmdW4oc29ydChyZXNfaXNvJHgpLCBjKG1pbihyZXNfaXNvJHlmKSAvMiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNfaXNvJHlmKSwgZiA9IDEpKQpkc19pc28gPC0gc2FwcGx5KDE6bnJvdyhjbG91ZCksIGZ1bmN0aW9uKGspIG1lYW4oKGZzX2lzb1tba11dKHBwX2Zha2VbLCBrXSkgLSBkYXRhJHgpXjIpXigxLzIpKSAKZHNfbG0gPC0gc2FwcGx5KDE6bnJvdyhjbG91ZCksIGZ1bmN0aW9uKGspIG1lYW4oKHBwX2Zha2VbLCBrXSAvIHJlc3NfbG1ba10gLSBkYXRhJHgpXjIpXigxLzIpKSAKCmRmX2RzIDwtIGRhdGEuZnJhbWUoY2xvdWQpCmRmX2RzIDwtIGNiaW5kKGRmX2RzLCBkc19pc28pCmRmX2RzIDwtIGNiaW5kKGRmX2RzLCBkc19sbSkKZ2dwbG90KGRhdGEgPSBkZl9kcykgKyBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyh4ID0gc2lnbWEsIHkgPSBkc19pc28pKQpnZ3Bsb3QoZGF0YSA9IGRmX2RzKSArIGdlb21fbGluZShtYXBwaW5nID0gYWVzKHggPSBzaWdtYSwgeSA9IGRzX2xtKSkKCnNpZ21hc1tkc19sbSA9PSBtaW4oZHNfbG0pXQpgYGAKCgpgYGB7cn0KIyBQcmlvciBzZXR0aW5ncyBmb3IgdGhlIHBhcmFtZXRlcnMKcHJpb3JfbGFtYmRhIDwtIHByaW9yX2Rpc3QoInVuaWZvcm0iLCAibGFtYmRhIixjKDAsIDUpKQpwcmlvcl9tdSA8LSBwcmlvcl9kaXN0KCJ1bmlmb3JtIiwgIm11IixjKC0zLDMpKQpwcmlvcl9zaWdtYSA8LSBwcmlvcl9kaXN0KCJ1bmlmb3JtIiwgInNpZ21hIiwgYygwLCAyKSkKcHJpb3JfZGlzdHJpYnV0aW9ucyA8LSBsaXN0KHByaW9yX2xhbWJkYSwgcHJpb3JfbXUsIHByaW9yX3NpZ21hKQptb2RlbF9wcmlvciA8LSBpbmRlcGVuZGVudF9wcmlvcnMocHJpb3JfZGlzdHJpYnV0aW9ucykKCiMgU2V0dGluZ3MgZm9yIHRoZSBhYmMgYWxnb3JpdGhtCnBvcFNpemUgPC0gNTAwOyAgTUNfUjwtIDUwMDsgYWNjIDwtIDAuMDE7IHNwX2JvdW5kcyA8LSBjKDEwXigtMTYpLCBJbmYpOyBlcHNfbWluIDwtIDAuMDEKcmVzX2FiYyA8LSBhYmMoZGF0YSwgbW9kZWxfcHJpb3IsIGxfbSwgcF9wLCBwb3BTaXplLCBNQ19SLCBhY2MsIHNwX2JvdW5kcywgZXBzX21pbikKYGBgCgpgYGB7cn0KIyBXZSByZXRyaWV2ZSB0aGUgY2xvdWQgb2YgcGFydGljbGVzIGFzc29jaWF0ZWQgdG8gZWFjaCBnZW5lcmF0aW9uCmNsb3VkX2RmcyA8LSBsYXBwbHkocmVzX2FiYyRDbG91ZHMsIGFzLmRhdGEuZnJhbWUpCmNsb3VkX2RmIDwtIGRvLmNhbGwocmJpbmQsIGNsb3VkX2RmcykKY2xvdWRfZGYkZ2VuZXJhdGlvbiA8LSBzb3J0KHJlcCgxOmxlbmd0aChyZXNfYWJjJENsb3VkcyksIHBvcFNpemUpKQpjbG91ZF9kZl9wbG90IDwtIHJiaW5kKAogIGRhdGEuZnJhbWUocGFybSA9IGNsb3VkX2RmJGxhbWJkYSwgcGFybV9uYW1lID0gImxhbWJkYSIsIGdlbmVyYXRpb24gPSBjbG91ZF9kZiRnZW5lcmF0aW9uKSwKICBkYXRhLmZyYW1lKHBhcm0gPSBjbG91ZF9kZiRzaWdtYSwgcGFybV9uYW1lID0gInNpZ21hIiwgZ2VuZXJhdGlvbiA9IGNsb3VkX2RmJGdlbmVyYXRpb24pCikKY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUgPC1hcy5mYWN0b3IoY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUpIApsZXZlbHMoY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUpIDwtIGMobGFtYmRhID0gVGVYKCIkXFxsYW1iZGEkIiksIHNpZ21hID0gVGVYKCIkXFxzaWdtYSQiKSkKZ2dwbG90Mjo6Z2dwbG90KGRhdGEgPSBjbG91ZF9kZiApICsgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGRhdGEgPSBjbG91ZF9kZiwgbWFwcGluZyA9IGFlcyh4PWxhbWJkYSwgY29sb3IgPSBhcy5mYWN0b3IoZ2VuZXJhdGlvbikpKSArIGdncGxvdDI6OmxhYnMoeD1UZVgoIiRcXGxhbWJkYSQiKSwgeSA9ICJEZW5zaXR5IiwgY29sb3IgPSAiR2VuZXJhdGlvbiIpICsgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAyMCkgKyBnZ3Bsb3QyOjp0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKyBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKGdncGxvdDI6OmFlcyh4aW50ZXJjZXB0PXRydWVfcGFybXNbLDFdKSwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIikKCmdncGxvdDI6OmdncGxvdChkYXRhID0gY2xvdWRfZGYgKSArIGdncGxvdDI6Omdlb21fZGVuc2l0eShkYXRhID0gY2xvdWRfZGYsIG1hcHBpbmcgPSBhZXMoeD1tdSwgY29sb3IgPSBhcy5mYWN0b3IoZ2VuZXJhdGlvbikpKSArIGdncGxvdDI6OmxhYnMoeD1UZVgoIiRcXG11JCIpLCB5ID0gIkRlbnNpdHkiLCBjb2xvciA9ICJHZW5lcmF0aW9uIikgKyBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDIwKSArIGdncGxvdDI6OnRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKSArIGdncGxvdDI6Omdlb21fdmxpbmUoZ2dwbG90Mjo6YWVzKHhpbnRlcmNlcHQ9dHJ1ZV9wYXJtc1ssMl0pLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiKQoKZ2dwbG90Mjo6Z2dwbG90KGRhdGEgPSBjbG91ZF9kZiApICsgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGRhdGEgPSBjbG91ZF9kZiwgbWFwcGluZyA9IGFlcyh4PXNpZ21hLCBjb2xvciA9IGFzLmZhY3RvcihnZW5lcmF0aW9uKSkpICsgZ2dwbG90Mjo6bGFicyh4PVRlWCgiJFxcc2lnbWEkIiksIHkgPSAiRGVuc2l0eSIsIGNvbG9yID0gIkdlbmVyYXRpb24iKSArIGdncGxvdDI6OnRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMjApICsgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsgZ2dwbG90Mjo6Z2VvbV92bGluZShnZ3Bsb3QyOjphZXMoeGludGVyY2VwdD10cnVlX3Bhcm1zWywzXSksIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpCmBgYAojIElJSSAtIE9wdGltaXphdGlvbiBiYXNlZCBvbiB0aGUgY29tbWVyY2lhbCBwcmVtaXVtcyB3aXRoIHJlZ3VsYXJpemF0aW9uCgoKYGBge3J9CiMgQWRkaW5nIHRoZSByZWd1bGFyaXphdGlvbiB0ZXJtcwpzcF9ib3VuZHMgPC0gYyhtaW4oZGZfcHAkcHAgLyBkYXRhJHgpLCBtYXgoZGZfcHAkcHAgLyBkYXRhJHgpKQojIHNwX2JvdW5kcyA8LSBjKDAuNiwgMC45NSkKZHMxIDwtIHNhcHBseSgxOm5jb2wocHBfZmFrZSksIGZ1bmN0aW9uKGspIHNxcnQobWVhbigocG1heChkYXRhJHggLSBwcF9mYWtlWyxrXSAvc3BfYm91bmRzWzFdLCAwKSApXjIpKSkKZHMyIDwtIHNhcHBseSgxOm5jb2wocHBfZmFrZSksIGZ1bmN0aW9uKGspIHNxcnQobWVhbigocG1heCggcHBfZmFrZVssa10gLyBzcF9ib3VuZHNbMl0gLSBkYXRhJHggLCAwKSApXjIpKSkKZHNfaXNvX3JlZyA8LSBkc19pc28gKyBkczEgKyBkczIKZHNfbG1fcmVnIDwtIGRzX2xtICsgZHMxICsgZHMyCmRmX2RzIDwtIGRhdGEuZnJhbWUoY2xvdWQpCmRmX2RzIDwtIGNiaW5kKGRmX2RzLCBkc19pc29fcmVnLCBkc19sbV9yZWcpCmdncGxvdChkYXRhID0gZGZfZHMpICsgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IHNpZ21hLCB5ID0gZHNfaXNvX3JlZykpCmdncGxvdChkYXRhID0gZGZfZHMpICsgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IHNpZ21hLCB5ID0gZHNfbG1fcmVnKSkKcHJpbnQoc2lnbWFzW2RzX2xtX3JlZz09bWluKGRzX2xtX3JlZyldKQpwcmludChzaWdtYXNbZHNfaXNvX3JlZz09bWluKGRzX2lzb19yZWcpXSk7IHByaW50KG1pbihkc19pc29fcmVnKSkKYGBgCmBgYHtyfQojIFByaW9yIHNldHRpbmdzIGZvciB0aGUgcGFyYW1ldGVycwpwcmlvcl9sYW1iZGEgPC0gcHJpb3JfZGlzdCgidW5pZm9ybSIsICJsYW1iZGEiLGMoMCwgNSkpCnByaW9yX211IDwtIHByaW9yX2Rpc3QoInVuaWZvcm0iLCAibXUiLGMoLTMsMykpCnByaW9yX3NpZ21hIDwtIHByaW9yX2Rpc3QoInVuaWZvcm0iLCAic2lnbWEiLCBjKDAsIDIpKQpwcmlvcl9kaXN0cmlidXRpb25zIDwtIGxpc3QocHJpb3JfbGFtYmRhLCBwcmlvcl9tdSwgcHJpb3Jfc2lnbWEpCm1vZGVsX3ByaW9yIDwtIGluZGVwZW5kZW50X3ByaW9ycyhwcmlvcl9kaXN0cmlidXRpb25zKQoKIyBTZXR0aW5ncyBmb3IgdGhlIGFiYyBhbGdvcml0aG0KcG9wU2l6ZSA8LSA1MDA7ICBNQ19SPC0gNTAwOyBhY2MgPC0gMC4wMDI7IHNwX2JvdW5kcyA8LSBjKG1pbihkZl9wcCRwcCAvIGRhdGEkeCksIG1heChkZl9wcCRwcCAvIGRhdGEkeCkpCmVwc19taW4gPC0gMC4wMDIKcmVzX2FiYyA8LSBhYmMoZGF0YSwgbW9kZWxfcHJpb3IsIGxfbSwgcF9wLCBwb3BTaXplLCBNQ19SLCBhY2MsIHNwX2JvdW5kcywgZXBzX21pbikKYGBgCgpgYGB7cn0KIyBXZSByZXRyaWV2ZSB0aGUgY2xvdWQgb2YgcGFydGljbGVzIGFzc29jaWF0ZWQgdG8gZWFjaCBnZW5lcmF0aW9uCmNsb3VkX2RmcyA8LSBsYXBwbHkocmVzX2FiYyRDbG91ZHMsIGFzLmRhdGEuZnJhbWUpCmNsb3VkX2RmIDwtIGRvLmNhbGwocmJpbmQsIGNsb3VkX2RmcykKY2xvdWRfZGYkZ2VuZXJhdGlvbiA8LSBzb3J0KHJlcCgxOmxlbmd0aChyZXNfYWJjJENsb3VkcyksIHBvcFNpemUpKQpjbG91ZF9kZl9wbG90IDwtIHJiaW5kKAogIGRhdGEuZnJhbWUocGFybSA9IGNsb3VkX2RmJGxhbWJkYSwgcGFybV9uYW1lID0gImxhbWJkYSIsIGdlbmVyYXRpb24gPSBjbG91ZF9kZiRnZW5lcmF0aW9uKSwKICBkYXRhLmZyYW1lKHBhcm0gPSBjbG91ZF9kZiRzaWdtYSwgcGFybV9uYW1lID0gInNpZ21hIiwgZ2VuZXJhdGlvbiA9IGNsb3VkX2RmJGdlbmVyYXRpb24pCikKY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUgPC1hcy5mYWN0b3IoY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUpIApsZXZlbHMoY2xvdWRfZGZfcGxvdCRwYXJtX25hbWUpIDwtIGMobGFtYmRhID0gVGVYKCIkXFxsYW1iZGEkIiksIHNpZ21hID0gVGVYKCIkXFxzaWdtYSQiKSkKZ2dwbG90Mjo6Z2dwbG90KGRhdGEgPSBjbG91ZF9kZiApICsgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGRhdGEgPSBjbG91ZF9kZiwgbWFwcGluZyA9IGFlcyh4PWxhbWJkYSwgY29sb3IgPSBhcy5mYWN0b3IoZ2VuZXJhdGlvbikpKSArIGdncGxvdDI6OmxhYnMoeD1UZVgoIiRcXGxhbWJkYSQiKSwgeSA9ICJEZW5zaXR5IiwgY29sb3IgPSAiR2VuZXJhdGlvbiIpICsgZ2dwbG90Mjo6dGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAyMCkgKyBnZ3Bsb3QyOjp0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKyBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKGdncGxvdDI6OmFlcyh4aW50ZXJjZXB0PXRydWVfcGFybXNbLDFdKSwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIikKCmdncGxvdDI6OmdncGxvdChkYXRhID0gY2xvdWRfZGYgKSArIGdncGxvdDI6Omdlb21fZGVuc2l0eShkYXRhID0gY2xvdWRfZGYsIG1hcHBpbmcgPSBhZXMoeD1tdSwgY29sb3IgPSBhcy5mYWN0b3IoZ2VuZXJhdGlvbikpKSArIGdncGxvdDI6OmxhYnMoeD1UZVgoIiRcXG11JCIpLCB5ID0gIkRlbnNpdHkiLCBjb2xvciA9ICJHZW5lcmF0aW9uIikgKyBnZ3Bsb3QyOjp0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDIwKSArIGdncGxvdDI6OnRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKSArIGdncGxvdDI6Omdlb21fdmxpbmUoZ2dwbG90Mjo6YWVzKHhpbnRlcmNlcHQ9dHJ1ZV9wYXJtc1ssMl0pLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiKQoKZ2dwbG90Mjo6Z2dwbG90KGRhdGEgPSBjbG91ZF9kZiApICsgZ2dwbG90Mjo6Z2VvbV9kZW5zaXR5KGRhdGEgPSBjbG91ZF9kZiwgbWFwcGluZyA9IGFlcyh4PXNpZ21hLCBjb2xvciA9IGFzLmZhY3RvcihnZW5lcmF0aW9uKSkpICsgZ2dwbG90Mjo6bGFicyh4PVRlWCgiJFxcc2lnbWEkIiksIHkgPSAiRGVuc2l0eSIsIGNvbG9yID0gIkdlbmVyYXRpb24iKSArIGdncGxvdDI6OnRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMjApICsgZ2dwbG90Mjo6dGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpICsgZ2dwbG90Mjo6Z2VvbV92bGluZShnZ3Bsb3QyOjphZXMoeGludGVyY2VwdD10cnVlX3Bhcm1zWywzXSksIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpCgpyZXNfYWJjJGRzW1sxMl1dCmBgYAoK